创建文档时使用mergeFields设置的Firestore文档无法按预期工作

时间:2019-05-29 08:00:35

标签: firebase google-cloud-firestore

嗨,我正在用这样的批处理写来保存文档:

batch.set(admin.firestore().collection('suuntoAppWorkoutQueue').doc(generateIDFromParts([serviceToken.userName, payload.workoutKey])), <QueueItemInterface>{
          userName: serviceToken.userName,
          workoutID: payload.workoutKey,
          retryCount: 0,
          processed: false, 
        }, {mergeFields: ['retryCount']});

根据文档:

  

将set()调用的行为更改为仅替换指定的字段路径。任何未指定的字段路径都将被忽略,并且保持不变。

上面说它只会替换。

但是,当我编写一个新文档时,例如doc ID不存在,mergeFields只写retryCount字段。

这是设计使然吗?

那么就不应该说:

  

将set()调用的行为更改为仅写入

代替:

  
    

将set()调用的行为更改为仅替换

  

1 个答案:

答案 0 :(得分:1)

我可以按照您关于写入/替换的说法。我没有亲自检查行为,但是如果文档不存在,则如果写字段是“写”或“更新”,则该行为比“替换”更适合描述行为,因为一开始就没有要替换的内容。

如果仅在文档已存在的情况下仅想更新该字段,则可以使用事务来进行更新。您可以使用该事务获取文档的最新版本,检查其是否存在,如果有,请进行更新。

let data = {
    userName: serviceToken.userName,
    workoutID: payload.workoutKey,
    retryCount: 0,
    processed: false, 
}

let db = admin.firestore()
let documentReference = db.collection('suuntoAppWorkoutQueue').doc(...)
db.runTransaction((transaction) =>
  transaction.get(documentRef).then((doc) => {
    if (doc.exists) {
      return t.update(documentRef, {retryCount: data.retryCount});
    } else {
      return t.set(documentRef, data);
    }
  }
).then(...).catch(...)

事务还具有原子性的优点。如果自获取以来服务器上的值已更改,则事务将失败。在这种情况下,Firestore实际上将重新运行您的代码以重新尝试更新。这消除了比赛条件。