首页 > 解决方案 > 添加具有特定 ID 的文档而不覆盖现有的文档

问题描述

我正在尝试将具有自定义唯一 ID 的文档添加到 Firestore,因此 set() 似乎是一种方式,因为 add() 将自动生成一个 ID。我想要的是,如果我添加具有现有 ID 的新文档,则会出现错误。

所以,我想添加 myObj,并且我希望文档的 id 是 myObj.id:

db.collection(COLLECTION_NAME).doc(myObj.code)
    .set(myObj)
    .then(() => {
      console.log('SENT!');
    })
    .catch(error => {
      console.error('Error: ', error);
    })

但是,当我添加一个具有现有 ID 的新文档时,它不会出现错误,而是会覆盖它。

我考虑过使用数据库规则,但我仍然不太清楚。我只需要拒绝该操作,但如果我想更新某个文档的字段,我应该能够做到这一点。

有没有办法做到这一点?

标签: javascriptfirebasegoogle-cloud-firestore

解决方案


根据您的评论更新

您的要求是“我想添加一个 ID 为 '1A2b3Cd' 的新文档,如果它不存在,如果它存在并且我尝试添加一个 ID 为 '1A2b3Cd' 的新文档,我想获得一个错误。”

我认为最好的方式是使用如下事务:

var docRef = db.collection(COLLECTION_NAME).doc(myObj.code);

return db.runTransaction(function(transaction) {
    return transaction.get(docRef).then(function(doc) {
        if (doc.exists) {
            throw "Document already exists!";
        }

        transaction.set(docRef, myObj);
    });
}).then(function() {
    console.log("Transaction successfully committed!");
}).catch(function(error) {
    console.log("Transaction failed: ", error);
});

文档中所述,使用set()方法“如果文档尚不存在,则将其创建”。


如果您想“更新某个(现有)文档的字段”,您应该为该方法提供一个SetOptions对象,如下所示(文档摘录):merge: trueset()

var cityRef = db.collection('cities').doc('BJ');

var setWithMerge = cityRef.set({
    capital: true
}, { merge: true });

所以,在你的情况下:

db.collection(COLLECTION_NAME).doc(myObj.code)
    .set(myObj, { merge: true })
    .then(() => {
      console.log('SENT!');
    })
    .catch(error => {
      console.error('Error: ', error);
    })

请注意,该update()方法的不同之处在于,使用 时update(),“如果应用于不存在的文档,更新将失败”。


推荐阅读