You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Native中Firestore查询多需求实现问题:获取今日/未来预约及自动删除过期预约

React Native Firestore 查询:分类今日/未来预约并自动删除过期预约

问题描述

我在React Native中使用Firestore查询预约数据时遇到了问题,当前的代码只能筛选今日的预约,但我还需要实现三个功能:

  1. 将今日的所有预约整理为一个对象;
  2. 将今日之后的所有预约整理为一个对象;
  3. 当预约的时间超过当前时间时,自动从数据库中删除该预约。

当前使用的代码如下:

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);
}

代码细节说明

  • 日期判断更精准:用momentisBeforeisBetween方法替代字符串格式化对比,避免时区或格式不一致导致的错误;
  • 高效批量删除:使用Firestore的batch操作,比逐个删除文档更高效,单批次最多支持500个操作;
  • 数据分类清晰:把今日和未来的预约分别存入不同数组,方便后续redux状态管理和页面渲染;
  • 健壮性提升:添加了用户登录判断和try/catch错误捕获,避免因未登录或网络问题导致的崩溃。

内容的提问来源于stack exchange,提问作者Osama Tab

火山引擎 最新活动