karste
karste

Reputation: 27

Firebase function onUpdate doesnt update another document "Cannot read property 'update' of undefined "

this is my code:

  exports.updateCourseName = functions.firestore
    .document('courses/{courseId}')
    .onUpdate((change, context) => {
      const newValue = change.after.data().name;
      const previousValue = change.before.data().name;
      const course1Id = context.params.courseId;
      if(newValue != previousValue){
        console.log("veränderung!")
        return admin.firestore().collection("sets").where("course.id", "==", course1Id)
        .get()
        .then((querySnapshot) => {
          if (!querySnapshot.empty) {
                querySnapshot.docs[0].course.update({name: newValue})
          }
        })
      }
    });
    

This my firebase structure: courses sets

The code is running with the error: TypeError: Cannot read property 'update' of undefined . But after i change the name in the "courses" ( here is the name "dergerat", the name doesnt change in the sets/{set_id}/course/name. I get the log "veränderung!" after changing the name so this part is working fine. Is there some problem with the return part? Or what am I doing wrong?

Upvotes: 0

Views: 159

Answers (2)

Renaud Tarnec
Renaud Tarnec

Reputation: 83103

Doing

querySnapshot.docs[0].course.update({author : newValue})

cannot work.

With querySnapshot.docs[0] you get a QueryDocumentSnapshot and there is no course property for this object. The update() method is a method of a DocumentReference so you should do something along the following lines:

exports.updateCourseName = functions.firestore
    .document('courses/{courseId}')
    .onUpdate((change, context) => {
        const newValue = change.after.data().name;
        const previousValue = change.before.data().name;
        const course1Id = context.params.courseId;
        if (newValue != previousValue) {
            console.log("veränderung!")
            return admin.firestore().collection("sets").where("course.id", "==", course1Id)
                .get()
                .then((querySnapshot) => {
                    if (!querySnapshot.empty) {
                        return querySnapshot.docs[0].ref.update({ "course.name": newValue })
                    } else {
                        return null;
                    }
                })
        } else {
          return null;
        }
    });

We make the assumption there is only one doc returned by the query, so we can use docs[0] to get the QueryDocumentSnapshot corresponding to the set doc. We then use the ref property of the QueryDocumentSnapshot and we update the field in the nested object.


PS: See also the answer to your previous question and the importance to return, in your Cloud Function, the promise returned by the update() method.

Upvotes: 2

Dharmaraj
Dharmaraj

Reputation: 50840

There seems to be an issue with Document References there. You can try the following code:

exports.updateCourseName = functions.firestore
.document('courses/{courseId}')
.onUpdate((change, context) => {
  const newValue = change.after.data().name;
  const previousValue = change.before.data().name;
  const course1Id = context.params.courseId;
  if(newValue != previousValue){
    console.log("veränderung!")
    const setsRef = admin.firestore().collection("sets").where("course.id", "==", course1Id)
    return setsRef.get().then((querySnapshot) => {
      if (!querySnapshot.empty) return null
      const setId = querySnapshot[0].id
      return admin.firestore().collection("sets").doc(setId).update({"course.name": newValue}).then(() => {
          console.log("Data updated")
          return null
      })
    })
  }
});

After the query you can easily get ID of the set (or sets). If there are multiple sets which may contain the same set ID, you may have to use Batch Writes. The code above will only update the course name but you can update other fields similarly.

Upvotes: 2

Related Questions