Firebase 如何向数据库中的所有当前文档添加新字段?

Firebase 如何向数据库中的所有当前文档添加新字段?,firebase,google-cloud-firestore,google-cloud-functions,Firebase,Google Cloud Firestore,Google Cloud Functions,因此,我试图为我的应用程序实现一个新的云功能,但它需要对现有的数据库数据模型进行一些调整。我数据库中的每个用户都有一个字段,我每周都要更新该字段。我不希望这个功能每周为所有用户运行,因为这将是一个不必要的昂贵操作。相反,我只是决定通过在用户文档中存储“last updated”字段来跟踪上次更新该用户的时间 问题是我现有的400多个用户中没有一个有这个字段。因此,我正在寻找一种为数据库中所有现有用户添加此字段的方法,该字段在默认时间启动 我考虑过使用“批量写入”,如下所述: 但似乎需要指定要更

因此,我试图为我的应用程序实现一个新的云功能,但它需要对现有的数据库数据模型进行一些调整。我数据库中的每个用户都有一个字段,我每周都要更新该字段。我不希望这个功能每周为所有用户运行,因为这将是一个不必要的昂贵操作。相反,我只是决定通过在用户文档中存储“last updated”字段来跟踪上次更新该用户的时间

问题是我现有的400多个用户中没有一个有这个字段。因此,我正在寻找一种为数据库中所有现有用户添加此字段的方法,该字段在默认时间启动

我考虑过使用“批量写入”,如下所述:


但似乎需要指定要更新的每个文档的id。我的所有用户都有一个由Firestore生成的UUID,因此手动写入每个用户对我来说并不实际。我是否有办法在现有集合的每个文档中创建一个新字段?或者,如果不是的话,也许是我获取所有文档id列表的一种方法,这样我就可以遍历它并进行非常糟糕的批处理编写?我只需要做一次大规模的更新,然后再也不用做了。除非我发现一条新的数据,否则我将跟踪。

您可以使用云函数:例如,您将在下面找到一个云函数的代码,您可以通过在名为
BatchUpdateRigger的集合中创建一个文档来触发该函数(请注意,这只是触发云函数的一种方式。您可以很好地使用HTTPS云函数)

在这个云函数中,我们获取名为
collection
的集合的所有文档,并在每个文档中添加一个带有当前日期/时间(
ServerValue.TIMESTAMP
)的新字段。我们使用
Promise.all()
并行执行所有更新异步工作。不要忘记向
batchUpdateTrigger
集合添加写访问权限,并在云函数运行后删除它

 exports.batchUpdate = functions.firestore
  .document('batchUpdateTrigger/{triggerId}')
  .onCreate((snap, context) => {

    var collecRef = db.collection('collection');
    return admin.collecRef.get()
        .then(snapshot => {

           const ts = admin.database.ServerValue.TIMESTAMP;
           var promises = [];

           snapshot.forEach(doc => {
             const ref = doc.ref;

             promises.push(
               ref.update({
                   lastUpdate: ts
               });
             );

           });

           return Promise.all(promises);

        });

  });
您在这里可能遇到的一个问题是,您达到了云函数的超时时间。默认超时时间为60秒,但您可以在Google云控制台()上增加超时时间


另一种方法是,如您所说,使用批处理写入

云函数将如下所示:

 exports.batchUpdate = functions.firestore
  .document('batchUpdateTrigger/{triggerId}')
  .onCreate((snap, context) => {

    var collecRef = db.collection('collection');
    return admin.collecRef.get()
        .then(snapshot => {

           const ts = admin.database.ServerValue.TIMESTAMP;
           let batch = db.batch();

           snapshot.forEach(doc => {
             const ref = doc.ref;

             batch.update(ref, {
                   lastUpdate: ts
               });

           });

           return batch.commit();

        });

  });
但是,您需要在代码中管理批处理中500个操作的最大限制

以下是一种可能的简单方法(即不太复杂…)因为您将只设置一次默认值,并且只有几百个DOCs待处理,所以我们可以认为它是可接受的。下面的云函数将按批处理500个文档。因此,您可能不得不手动重新触发它,直到所有文档都被处理。
 exports.batchUpdate = functions.firestore
  .document('batchUpdateTrigger/{triggerId}')
  .onCreate((snap, context) => {

    var collecRef = db.collection('collection');
    return admin.collecRef.get()
        .then(snapshot => {

           const docRefsArray = [];
           snapshot.forEach(doc => {
              if (doc.data().lastUpdate == null) {
                 //We need to "treat" this doc
                 docRefsArray.push(doc.ref);
              )
            });

            console.log("Nbr of doc to treat: " + docRefsArray.length); //When the output is 0 you are done, i.e. all the docs are treated

            if (docRefsArray.length > 0) {

                const ts = admin.database.ServerValue.TIMESTAMP;

                let batch = db.batch();

                if (docRefsArray.length < 500) {

                   //We can "treat" all the documents in the QuerySnapshot
                   docRefsArray.forEach(ref => {
                      batch.update(ref, {
                         lastUpdate: ts
                      });
                   });

                } else {

                   //We need to "treat" only 500 documents
                   for (let i = 0; i < 500; i++) {
                      batch.update(docRefsArray[i], {
                         lastUpdate: ts
                      });
                }

                ​return batch.commit();

            } else {
                return null;
            }
        });
  });
exports.batchUpdate=functions.firestore
.document('BatchUpdateRigger/{triggerId}')
.onCreate((快照,上下文)=>{
var collecRef=db.collection('collection');
返回admin.collecRef.get()
。然后(快照=>{
常量docRefsArray=[];
snapshot.forEach(doc=>{
if(doc.data().lastUpdate==null){
//我们需要“治疗”这个医生
docRefsArray.push(doc.ref);
)
});
console.log(“待处理文档的Nbr:+docRefsArray.length);//当输出为0时,即完成处理所有文档
如果(docRefsArray.length>0){
const ts=admin.database.ServerValue.TIMESTAMP;
设batch=db.batch();
如果(docRefsArray.length<500){
//我们可以“处理”QuerySnapshot中的所有文档
docRefsArray.forEach(ref=>{
批次更新(参考{
更新:ts
});
});
}否则{
//我们只需要“处理”500份文件
for(设i=0;i<500;i++){
批处理更新(docRefsArray[i]{
更新:ts
});
}
​返回batch.commit();
}否则{
返回null;
}
});
});

最后一种技术的优点是,如果遇到云函数超时的问题,可以减少批处理的大小。

对于Android、iOS或web?帮助很大!谢谢。你的帖子总是解释得很好:)@Pooja谢谢你的评论!很高兴答案能帮到你!如何为Android、java做到这一点?@Ibramazin上面的代码是一个。它在Firebase/Google基础设施的后端执行,而不是在前端应用程序中执行。因此它适用于任何类型的应用程序,Android、iOS、Web。@RenaudTarnec请告诉我代码中的batchUpdateTrigger/{triggerId}是什么?我有一个名为“用户”的集合具有各种自动生成的文档(id),每个文档都有各种记录。我想在所有文档中添加一个新字段“电话号码”?请帮助PP。