Home > OS >  Firebase Cloud Function. Create documents in sub-collection of specific collections
Firebase Cloud Function. Create documents in sub-collection of specific collections

Time:12-15

here's the basic premise of what im trying to accomplish here. if a user ask a question about a product i want to send a notification to other users who currently own that product. basically saying "hey, so and so has a question about this product. maybe you can help since you own it already"

each userProfile collection has a subcollection called 'notify' where notifications are stored for various things. what i need to do is sort through the userProducts and find every user who owns the product and then create a notification post in only the notify sub-collections for those specific users who own that product.

here is the basic code. the first bit works in that it does return an array of userIDs who own that product. where im struggling now is getting it to create a new doc in the Notify sub-collection for just those specific users. is this possible to do?

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",
      });
    });
 });

CodePudding user response:

Your current solution is on the right track, but there are improvements that can be made.

  • Use a guard pattern for the data.question == true check.
  • You don't need to get userProfile/<uid> as you aren't using its contents.
  • When changing multiple documents at once, you should consider batching them together for simpler error handling.
  • ref.add(data) is shorthand for ref.doc().set(data) which you can use in the batched write to create new documents.
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
 });

Note: There is no special handling here for when no one has bought a product before. Consider pinging the product's owner too.

  • Related