0

I have been trying to update a nested object in Firestore when a cloud function is triggered as described in the documentation.

Here's the onCreate trigger:

// Cloud function to increment count total product reviews
exports.incTotalProductReviews = functions.firestore
  .document("users/{uid}/productReviewRequests/{productReviewReq}")
  .onCreate((snap, context) => {
    // Get the userID & eventID from context
    const userID = context.params.uid;
    const eventId = context.eventId;
    const data = snap.data()
    // Get doc ref 
    const userStatisticsRef = admin.firestore().collection("userStatistics").doc(userID);
    const eventRef = admin.firestore().collection("pastEvents").doc(eventId)

    return eventRef.get()
      .then((doc) => {

        //Check for rerun - idempotent function
        if (doc.exists) {
          return functions.logger.log("Event already happened.");

        } else {

          return userStatisticsRef.update({
            "productReview.REQUESTED": admin.firestore.FieldValue.increment(1)
          })

        }
      })
      .then(() => eventRef.set({ timestamp: admin.firestore.Timestamp.now() }))
      .catch((err) => { functions.logger.error(err) });
  });

The result is that the nested object does not update, instead a new field with the key "productReview.REQUESTED" is created and updated.

Firestore after the trigger is run

My goal was to use a dynamic key as described in this answer, but it had the same effect.

Is there something that I'm doing wrong, or is it a bug in Firestore/Cloud functions?

UPDATE

So I tried various approaches and it finally worked - kinda. (only for update() method, not set())

  1. Using .set({"productReview.REQUESTED": admin.firestore.FieldValue.increment(1)}, {merge: true}) has the same effect as described in the question, i.e. the nested field does not update, instead a new field with the key productReview.REQUESTED is created and updated. This is a problem since I want to update a document but there is no guarantee that the document exists.

  2. Using the .update({"productReview.REQUESTED": admin.firestore.FieldValue.increment(1)}) worked finally (it didn't before) - but the drawback being that now I have to check if the document exists/ensure that the document exists.

Nikhil Kothari
  • 235
  • 2
  • 8
  • Can you try adding `.then(() => console.log("data updated")).catch(e =>console.log(e))` to that update operation and share any logs ? – Dharmaraj Aug 17 '21 at 15:25
  • I have added both of those things, and the function does not throw any error. In fact, it runs the code, and updates the value in the database, albeit not the nested field. – Nikhil Kothari Aug 17 '21 at 15:35
  • What are the versions of `firebase-functions` and `firebase-admin`? You can find that in the `packkage.json`file under the `functions`directory. – Renaud Tarnec Aug 17 '21 at 15:47
  • Sure, here they are: firebase-admin: v9.6.0, firebase-functions: v3.13.2. I assumed it was an issue with the libraries, so I updated them, but the issue persists. – Nikhil Kothari Aug 17 '21 at 15:50
  • Your code should work. Can you share the entire content of the Cloud Function, not just some few lines? – Renaud Tarnec Aug 17 '21 at 15:52
  • Sure, just updated the question with the entire trigger. – Nikhil Kothari Aug 17 '21 at 15:55
  • You should do `.then(() => return eventRef.set({ timestamp: admin.firestore.Timestamp.now() }))` to return the entire promise chain and in `if (doc.exists)` block, do not return the call to `functions.logger.log` but either throw an exception or return e.g. `null`. I don't think these changes will solve your problem but they are necessary to correctly manage the CF life cycle. – Renaud Tarnec Aug 17 '21 at 16:09
  • Yeah that was the plan - the code is incomplete. I need to make the key dynamic, and wrap the whole thing in a transaction. But I wasn't able to get the basic functionality working. – Nikhil Kothari Aug 17 '21 at 16:13

0 Answers0