递归更新子collectioncollectionGroup的Firestore云端函数。

问题描述 投票:3回答:1

我有这个云功能。

import pLimit from "p-limit";


const syncNotificationsAvatar = async (
  userId: string,
  change: Change<DocumentSnapshot>
) => {
  if (!change.before.get("published") || !change.after.exists) {
    return;
  }

  const before: Profile = change.before.data() as any;
  const after: Profile = change.after.data() as any;
  const keysToCompare: (keyof Profile)[] = ["avatar"];
  if (
    arraysEqual(
      keysToCompare.map((k) => before[k]),
      keysToCompare.map((k) => after[k])
    )
  ) {
    return;
  }

  const limit = pLimit(1000);

  const input = [
    limit(async () => {
      const notifications = await admin
        .firestore()
        .collectionGroup("notifications")
        .where("userId", "==", userId)
        .limit(1000)
        .get()

      await Promise.all(
        chunk(notifications.docs, 500).map(
          async (docs: admin.firestore.QueryDocumentSnapshot[]) => {
            const batch = admin.firestore().batch();
            for (const doc of docs) {
              batch.update(doc.ref, {
                avatar: after.avatar
              });
            }
            await batch.commit();
          }
        )
      );
    })
  ];

  return await Promise.all(input);
};


我怎么能递归地更新 notifications 集合,但首先将查询限制在 1.000 文件(直到没有更多的文件),然后在 batch.update 他们?我担心这个查询会超时,因为随着时间的推移,收集的东西可能会越来越多,我有一个云函数:从 "p-limit "导入pLimit; const syncNotificationsAvatar = async ( userId: string); const syncNotificationsAvatar = async ( userId: string)。

javascript node.js firebase google-cloud-firestore google-cloud-functions
1个回答
1
投票

发一个我研究出来的解决方案,虽然没有按照问题的上下文,但是可以很容易的结合起来。希望能帮到别人。

import * as admin from "firebase-admin";

const onResults = async (
  query: admin.firestore.Query,
  action: (batch: number, docs: admin.firestore.QueryDocumentSnapshot[]) => Promise<void>
) => {
  let batch = 0;
  const recursion = async (start?: admin.firestore.DocumentSnapshot) => {
    const { docs, empty } = await (start == null
      ? query.get()
      : query.startAfter(start).get());
    if (empty) {
      return;
    }
    batch++;
    await action(
      batch,
      docs.filter((d) => d.exists)
    ).catch((e) => console.error(e));
    await recursion(docs[docs.length - 1]);
  };
  await recursion();
};

const getMessages = async () => {
  const query = admin
    .firestore()
    .collection("messages")
    .where("createdAt", ">", new Date("2020-05-04T00:00:00Z"))
    .limit(200);

  const messages: FirebaseFirestore.DocumentData[] = [];

  await onResults(query, async (batch, docs) => {
    console.log(`Getting Message: ${batch * 200}`);
    docs.forEach((doc) => {
       messages.push(doc.data());
    });
  });
  return messages;
};

© www.soinside.com 2019 - 2024. All rights reserved.