首页 > 解决方案 > 如果不存在,则使用“新”字段写入文档,否则合并字段

问题描述

使用 firebase 函数,我每 x 分钟轮询一次 API,以获取我保存的一组项目。假设每个项目看起来像这样:

{ name: "John", id: 1}

如果这是一个新文档,我想将其存储在 firestore 中,并带有一个state值为“New”的字段:

[1]: { name: "John", state: "New"}

但是,如果我以前看过这个文档(它在具有该 ID 的 Firestore 中),我想更新里面的数据,但保持状态不变,即

前:

[1]: { name: "John", state: "Processed"}

后:

[1]: {name: "UpdatedName", state: "Processed"}

我怎样才能做到这一点?对于已经存在的文档,我可以使用mergeFields SetOption来实现这一点,因此排除 state 字段 - 但不幸的是,随后到达的全新文档未设置为state: "New".

另一种选择是使用firebase检查每个文档是否存在id,但这似乎不太理想并且难以实现(我最终在foreach循环中进行了多个查询)。这大致是我的代码:

const batch = db.batch();
response.data.items.forEach(item => {
  const document = {
    name: item.name
    state: "New"
  };
  batch.set(
    db.collection(collectionPath).doc(item.id),
    document,
    {
      mergeFields: Object.keys(document).filter(
        field => field !== 'state'
      ),
    }
  );
});
return batch.commit();

标签: node.jsfirebasegoogle-cloud-firestoregoogle-cloud-functions

解决方案


由于文档的新状态在文档的现有状态(或缺少状态)上,因此您需要在此处执行事务。

let docRef = db.collection(collectionPath).doc(item.id);
let transaction = db.runTransaction(t => {
  return t.get(docRef)
    .then(doc => {
      if (doc.exists()) {
         t.update(docRef, { state: "Processed" });
      }
      else {
         t.set(docRef, { name: "John", state: "New" });
      }
    });
}).then(result => {
  console.log('Transaction success!');
}).catch(err => {
  console.log('Transaction failure:', err);
});

推荐阅读