React Native中Firestore查询多需求实现问题:获取今日/未来预约及自动删除过期预约
React Native Firestore 查询:分类今日/未来预约并自动删除过期预约
问题描述
我在React Native中使用Firestore查询预约数据时遇到了问题,当前的代码只能筛选今日的预约,但我还需要实现三个功能:
- 将今日的所有预约整理为一个对象;
- 将今日之后的所有预约整理为一个对象;
- 当预约的时间超过当前时间时,自动从数据库中删除该预约。
当前使用的代码如下:
await firebase.firestore() .collection("patients") .doc(firebase.auth().currentUser.uid) .collection("appointment") .orderBy("dateTime", "asc") .get() .then((result) => { let appointment = result.docs.map((doc) => { const data = doc.data(); const id = doc.id; const currentDate = moment().format("YYYY-MM-DD"); const dt=new moment(doc.data().dateTime,'YYYY-MM-DD').format('YYYY-MM-DD'); if(dt===currentDate){ return { id, ...data }; } }); dispatch({ type: GET_APPOINTMENT, appointment }); });
解决方案
我来帮你一步步实现这三个功能,先重构代码逻辑,同时兼顾性能和可读性:
1. 统一日期时间判断逻辑
首先明确:如果你的dateTime字段在Firestore中存的是Timestamp类型(这是推荐做法),直接用moment转换会更准确;如果是字符串格式,确保和moment解析格式一致。先定义几个关键时间节点:
const now = moment(); // 当前时间的moment实例 const todayStart = now.startOf('day'); // 今日0点整 const todayEnd = now.endOf('day'); // 今日23:59:59
2. 完整实现代码
try { const userId = firebase.auth().currentUser?.uid; if (!userId) { console.error("用户未登录,无法获取预约数据"); return; } // 获取用户预约集合的引用 const appointmentColRef = firebase.firestore() .collection("patients") .doc(userId) .collection("appointment"); // 获取所有预约数据 const querySnapshot = await appointmentColRef.orderBy("dateTime", "asc").get(); // 初始化三个变量:今日预约、未来预约、过期预约ID列表 let todayAppointments = []; let futureAppointments = []; const expiredAppointmentIds = []; // 遍历所有预约文档 querySnapshot.forEach(doc => { const docData = doc.data(); const docId = doc.id; // 将Firestore Timestamp转成moment实例 const appointmentTime = moment(docData.dateTime.toDate()); // 判断是否过期:预约时间早于当前时间 if (appointmentTime.isBefore(now)) { expiredAppointmentIds.push(docId); } // 判断是否是今日预约:在今日0点到23:59区间内 else if (appointmentTime.isBetween(todayStart, todayEnd, undefined, '[]')) { todayAppointments.push({ id: docId, ...docData }); } // 其余的就是今日之后的预约 else { futureAppointments.push({ id: docId, ...docData }); } }); // 需求3:批量删除过期预约 if (expiredAppointmentIds.length > 0) { const batch = firebase.firestore().batch(); expiredAppointmentIds.forEach(id => { batch.delete(appointmentColRef.doc(id)); }); await batch.commit(); console.log(`已成功删除${expiredAppointmentIds.length}个过期预约`); } // 需求1&2:分发整理好的两类预约数据到redux dispatch({ type: GET_APPOINTMENT, payload: { todayAppointments, futureAppointments } }); } catch (error) { console.error("处理预约数据时出错:", error); }
代码细节说明
- 日期判断更精准:用
moment的isBefore、isBetween方法替代字符串格式化对比,避免时区或格式不一致导致的错误; - 高效批量删除:使用Firestore的
batch操作,比逐个删除文档更高效,单批次最多支持500个操作; - 数据分类清晰:把今日和未来的预约分别存入不同数组,方便后续redux状态管理和页面渲染;
- 健壮性提升:添加了用户登录判断和
try/catch错误捕获,避免因未登录或网络问题导致的崩溃。
内容的提问来源于stack exchange,提问作者Osama Tab




