You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Firebase将Bookings关联至Users与Restaurants集合的方法

Firebase Bookings数据同步至Users和Restaurants集合方案

一、实时自动同步(推荐:Cloud Functions)

这是最可靠的自动同步方案,当Bookings集合的文档发生创建、更新、删除操作时,会自动触发同步逻辑。

步骤1:初始化Cloud Functions

确保本地已安装Firebase CLI,在项目目录执行:

firebase init functions

选择JavaScript/TypeScript,按提示完成初始化。

步骤2:编写同步函数

在functions/index.js(或.ts)中写入以下代码:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

const db = admin.firestore();

// 监听Bookings集合的所有写入操作(创建/更新/删除)
exports.syncBookingsToUsersAndRestaurants = functions.firestore
  .document("Bookings/{bookingId}")
  .onWrite(async (change, context) => {
    const bookingId = context.params.bookingId;
    const batch = db.batch();

    // 获取新旧booking数据
    const oldBooking = change.before.data();
    const newBooking = change.after.data();

    // 同步到用户侧
    if (newBooking?.UserID) {
      const userRef = db.collection("Users").doc(newBooking.UserID);
      // 创建/更新时添加booking
      if (newBooking) {
        batch.set(userRef, {
          bookings: admin.firestore.FieldValue.arrayUnion({
            bookingID: bookingId,
            ...newBooking
          })
        }, { merge: true });
      }
      // 删除时移除对应booking
      else if (oldBooking) {
        batch.set(userRef, {
          bookings: admin.firestore.FieldValue.arrayRemove({
            bookingID: bookingId,
            ...oldBooking
          })
        }, { merge: true });
      }
    }

    // 同步到餐厅侧(逻辑与用户侧一致)
    if (newBooking?.restaurantID) {
      const restaurantRef = db.collection("Restaurants").doc(newBooking.restaurantID);
      if (newBooking) {
        batch.set(restaurantRef, {
          bookings: admin.firestore.FieldValue.arrayUnion({
            bookingID: bookingId,
            ...newBooking
          })
        }, { merge: true });
      } else if (oldBooking) {
        batch.set(restaurantRef, {
          bookings: admin.firestore.FieldValue.arrayRemove({
            bookingID: bookingId,
            ...oldBooking
          })
        }, { merge: true });
      }
    }

    // 提交批量操作
    return batch.commit().catch(err => {
      functions.logger.error("同步失败:", err);
      throw err;
    });
  });

步骤3:部署函数

执行命令将函数部署到Firebase:

firebase deploy --only functions

二、历史数据一次性同步

如果需要将已有的Bookings数据批量同步到Users和Restaurants,可编写一次性执行脚本:

const admin = require("firebase-admin");
admin.initializeApp();

const db = admin.firestore();

async function syncExistingBookings() {
  const bookingsSnapshot = await db.collection("Bookings").get();
  const batch = db.batch();

  bookingsSnapshot.forEach(doc => {
    const booking = doc.data();
    const bookingId = doc.id;

    // 同步到用户
    if (booking.UserID) {
      const userRef = db.collection("Users").doc(booking.UserID);
      batch.set(userRef, {
        bookings: admin.firestore.FieldValue.arrayUnion({
          bookingID: bookingId,
          ...booking
        })
      }, { merge: true });
    }

    // 同步到餐厅
    if (booking.restaurantID) {
      const restaurantRef = db.collection("Restaurants").doc(booking.restaurantID);
      batch.set(restaurantRef, {
        bookings: admin.firestore.FieldValue.arrayUnion({
          bookingID: bookingId,
          ...booking
        })
      }, { merge: true });
    }
  });

  await batch.commit();
  console.log("历史数据同步完成");
}

syncExistingBookings().catch(err => console.error("同步出错:", err));

运行前需配置好Firebase Admin SDK的服务账号密钥,执行node sync-script.js即可完成同步。

注意事项

  • 若Users/Restaurants集合中无bookings字段,merge: true会自动创建该字段。
  • 为避免重复同步,确保每个booking的唯一标识(如bookingID)被包含在同步数据中,Firebase会自动忽略数组内的重复元素。
  • 删除操作时,arrayRemove需要传入与添加时完全一致的对象,若仅存储bookingID会更高效,移除时仅传ID即可。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:08:16