Firestore云功能以递归方式更新子集合/集合组 [英] Firestore cloud function to recursively update subcollection/collectionGroup

查看:52
本文介绍了Firestore云功能以递归方式更新子集合/集合组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有此云功能:

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个?恐怕此查询会超时,因为收集会随着时间的推移而增长.

How can I recursively update the notifications collection but first limit the query to 1.000 documents (until there are not more documents) and then batch.update them? I'm afraid this query will timeout since collection could grow big over time.

推荐答案

我提出了一个解决方案,虽然没有遵循问题的上下文,但是可以轻松地将其组合在一起.希望对别人有帮助.

Posting a solution I worked out, not following the context of the question though but it can easily be combined. Hope it helps someone else.

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

这篇关于Firestore云功能以递归方式更新子集合/集合组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆