我有这个云功能。
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)。
发一个我研究出来的解决方案,虽然没有按照问题的上下文,但是可以很容易的结合起来。希望能帮到别人。
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;
};