Firebase 云函数。在特定集合的子集合中创建文档
Firebase Cloud Function. Create documents in sub-collection of specific collections
这是我要在这里完成的工作的基本前提。如果用户询问有关产品的问题,我想向当前拥有该产品的其他用户发送通知。基本上是说“嘿,某某对这个产品有疑问。也许你可以帮忙,因为你已经拥有它了”
每个 userProfile 集合都有一个名为 'notify' 的子集合,其中存储各种通知。我需要做的是对 userProducts 进行排序并找到拥有该产品的每个用户,然后仅在拥有该产品的特定用户的通知子集合中创建通知 post。
这是基本代码。第一点的工作原理是它 return 拥有该产品的用户 ID 数组。我现在挣扎的地方是让它在 Notify 子集合中为那些特定用户创建一个新文档。这可能吗?
exports.Questions = functions.firestore
.document("/userPost/{id}")
.onCreate(async (snap, context) => {
const data = snap.data();
if (data.question == true) {
const userProducts = await db
.collection("userProducts")
.where("product", "==", data.tag)
.get();
const userData = userProducts.docs.map((doc) => doc.data().userId);
await db
.collection("userProfile")
.where("userId", "in", userData)
.get()
.then((querySnapshot) => {
return querySnapshot.docs.ref.collection("notify").add({
message: "a user has asked about a product you own",
});
});
});
您当前的解决方案是正确的,但还可以进行改进。
- 使用 guard pattern 进行
data.question == true
检查。
- 您不需要获取
userProfile/<uid>
,因为您没有使用它的内容。
- 一次更改多个文档时,您应该考虑 batching them together 以简化错误处理。
ref.add(data)
是 shorthand for ref.doc().set(data)
,您可以在批量写入中使用它来创建新文档。
exports.Questions = functions.firestore
.document("/userPost/{id}")
.onCreate(async (snap, context) => {
const data = snap.data();
if (!data.question) {
console.log("New post not a question. Ignored.")
return;
}
const userProducts = await db
.collection("userProducts")
.where("product", "==", data.tag)
.get();
const userIds = userProducts.docs.map(doc => doc.get("userId")); // more efficient than doc.data().userId
// WARNING: Limited to 500 writes at once.
// If handling more than 500 entries, split into groups.
const batch = db.batch();
const notificationContent = {
message: "a user has asked about a product you own",
};
userIds.forEach(uid => {
// creates a ref to a new document under "userProfile/<uid>/notify"
const notifyDocRef = db.collection(`userProfile/${uid}/notify`).doc();
batch.set(notifyDocRef, notificationContent);
});
await batch.commit(); // write changes to Firestore
});
注意:对于没有人购买过的产品,这里没有特殊处理。也考虑联系产品的所有者。
这是我要在这里完成的工作的基本前提。如果用户询问有关产品的问题,我想向当前拥有该产品的其他用户发送通知。基本上是说“嘿,某某对这个产品有疑问。也许你可以帮忙,因为你已经拥有它了”
每个 userProfile 集合都有一个名为 'notify' 的子集合,其中存储各种通知。我需要做的是对 userProducts 进行排序并找到拥有该产品的每个用户,然后仅在拥有该产品的特定用户的通知子集合中创建通知 post。
这是基本代码。第一点的工作原理是它 return 拥有该产品的用户 ID 数组。我现在挣扎的地方是让它在 Notify 子集合中为那些特定用户创建一个新文档。这可能吗?
exports.Questions = functions.firestore
.document("/userPost/{id}")
.onCreate(async (snap, context) => {
const data = snap.data();
if (data.question == true) {
const userProducts = await db
.collection("userProducts")
.where("product", "==", data.tag)
.get();
const userData = userProducts.docs.map((doc) => doc.data().userId);
await db
.collection("userProfile")
.where("userId", "in", userData)
.get()
.then((querySnapshot) => {
return querySnapshot.docs.ref.collection("notify").add({
message: "a user has asked about a product you own",
});
});
});
您当前的解决方案是正确的,但还可以进行改进。
- 使用 guard pattern 进行
data.question == true
检查。 - 您不需要获取
userProfile/<uid>
,因为您没有使用它的内容。 - 一次更改多个文档时,您应该考虑 batching them together 以简化错误处理。
ref.add(data)
是 shorthand forref.doc().set(data)
,您可以在批量写入中使用它来创建新文档。
exports.Questions = functions.firestore
.document("/userPost/{id}")
.onCreate(async (snap, context) => {
const data = snap.data();
if (!data.question) {
console.log("New post not a question. Ignored.")
return;
}
const userProducts = await db
.collection("userProducts")
.where("product", "==", data.tag)
.get();
const userIds = userProducts.docs.map(doc => doc.get("userId")); // more efficient than doc.data().userId
// WARNING: Limited to 500 writes at once.
// If handling more than 500 entries, split into groups.
const batch = db.batch();
const notificationContent = {
message: "a user has asked about a product you own",
};
userIds.forEach(uid => {
// creates a ref to a new document under "userProfile/<uid>/notify"
const notifyDocRef = db.collection(`userProfile/${uid}/notify`).doc();
batch.set(notifyDocRef, notificationContent);
});
await batch.commit(); // write changes to Firestore
});
注意:对于没有人购买过的产品,这里没有特殊处理。也考虑联系产品的所有者。