简体   繁体   中英

Firebase firestore: how to query relevant documents and then update each of them

I am developing a web app on Firebase/firestore, in which users can sign in and write their own posts. The data are stored in the following way:

-User information are stored as under collection('user').doc('uid').

-Information about posts the user has written are stored in collection('post').doc('postid'), and the doc has 'userinfo' and 'uid' fields. The 'userinfo' field contains exact copy of what is stored in 'uid' doc, just in object format.

Here are the operations that I want to do:

  1. When the user changes the data, the changes are reflected in the document.

  2. Look for the all the posts that the user has written based on 'uid' data, and then update userinfo in those data.

The last part is tricky for me. The Firebase documentations cover situations where the references are pretty much static, ie you know the exact path to write/update. What I am trying to do is look for a set of documents that is not necessarily static, and then update each of them.

Here is the code I wrote for this effort. The first part works without any problem. Of course, the second part doesn't work. :) What would be the code to do the do the second part?

 const update = () => {
             //This part is for updating user information. This works without any problem.
             firebase.firestore().collection('user').doc(user.uid).update({
                 username: username1,
                 nickname: nickname1,
                 intro: intro1 
             })
            .then(()=>{
             //This part is for updating all of the document that the user has written based on 'uid' value. This doesn't work. 
             //Below code is probably way off, but it shows where I am going and what I am trying to do.
             firebase.firestore().collection('post').where('uid','==',user.uid).get()
                 .then((querysnapshot)=>{
                     querysnapshot.forEach((doc)=>{
                         let ref=firebase.firestore().collection('post').doc(doc.id);
                             ref.update({
                                 userinfo: {nickname:nickname1,username:username1,intro:intro1}
                             })
                        })
                     })
                }).then(()=>{
                    alert("Successfully updated!");
                    window.location.href='/'+username1;
                }).catch((error)=>{
                    alert("Error!"); 
                })
}

Thanks a lot in advance!

What's the error that you get running this code? It seems on the right track for me.

But despite that, here are some suggestions to deal with this kind of update:

  • Don't do the second part on the client side, do it on the server side with a Firestore Trigger (create a onUpdate trigger in the user collection in your case): https://firebase.google.com/docs/functions/firestore-events .

    • The problem of doing in the client side, is because if the user closes the page/browser or the site goes offline in the middle of the update, you will have inconsistent data.
  • You don't need to recreate the DocumentReference after getting the query result, the docs returned already have a.ref that you can call.ref.update() directly.

EDIT : If you want to keep your original code (updating on client side), the problem of the navigation occurring before all the updates to conclude is because ref.update() returns a promise.

So the update queue is asynchronous being performed on database when the client navigates away.

To solve this, I would use a Promise.all() to wait all updates being completed.

firebase.firestore().collection('post').where('uid','==',user.uid).get()
   .then((querysnapshot)=>{
       const promises = [];
       querysnapshot.forEach((doc)=>{
           promises.push(doc.ref.update({
               userinfo: {nickname:nickname1,username:username1,intro:intro1}
           });
       });
       Promise.all(promises).then(()=>{window.location.href='/'+username1;});
   });

Or using the await syntax (I think it's easier to maintain and understand):

const querysnapshot = await firebase.firestore().collection('post').where('uid','==',user.uid).get();

const promises = [];
querysnapshot.forEach((doc)=>{
   promises.push(doc.ref.update({
      userinfo: {nickname:nickname1,username:username1,intro:intro1}
   });
});
await Promise.all(promises);
window.location.href='/'+username1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM