如果某些文档可能被删除,如何成功进行批量提交?

时间:2018-03-17 03:32:56

标签: firebase google-cloud-firestore

假设我有这样的结构:

items: {
  id1: {
    likes: 123
  },
  id2: {
    likes: 456
  },
  id3: {
    sourceId: 'id1',
    likes: 123
  },
  id4: {
    sourceId: 'id1',
    likes: 123
  }
  [,...]
}

其中任何项目可以是源项目或引用源项目的项目。引用源项目的目的是使所有共享相同sourceId的项目的计数器保持一致。

因此,当我更改源项目的计数器时,我想将该计数器的值批量写入所有具有该项目作为其sourceId的项目。

我的关注

假设我在引用某些sourceId的文档中读取,然后我将批量更改提交给所有这些文档。如果批量文档中的一小部分文档在读入文档后的小窗口中被删除,或者发生了罕见但可能的写入速率冲突,该怎么办?没有计数器更新,因为1或2个文档无法更新?

是否可以提交一个批处理,独立地将更改写入每个文档,如果一个文档失败,它对其他文档是否写入没有影响?

或者对于这种情况,最好在引用某些sourceId的文档中读取,然后并行地将更改写入每个文档,以实现写入独立性。 我不喜欢这种方法,因为请求数量就是批量的大小。

你有什么想法?

2 个答案:

答案 0 :(得分:1)

仔细阅读BatchWrite的API文档。它会回答你的问题。既然您没有显示批量代码(您使用的是set?update吗?),我们必须查看API文档来评估失败案例:

  

创建()

     

如果文档存在于其位置,这将使批处理失败。

听起来你可能没有使用create(),但这是失败的情况。

  

组()

     

如果文档尚不存在,则会创建该文档。

因此,如果在批量提交之前删除了文档,则集合不会失败。

  

更新()

     

如果文档尚未存在,则更新失败并且整个更新失败   批次将被拒绝。

因此,如果您尝试更新不存在的文档,批处理将失败。

如果您想决定如何处理每个文档,根据其存在和内容,然后控制失败案例,使用transaction

答案 1 :(得分:0)

如果我理解你的问题,我有一个类似的情况,这就是我做的方式。首先,我使用生成的通用ID,uid,用于我的所有项目键/ id。然后,你做的是孙子,只需写下与之关联的父母的uid。每个孙子都可以与多个父母联系。

在创建新项目时,您必须使用项目的uid递归更新父项,以便父项记录其所有相关子项目。

    fetchPromise = [];
    fetchArray = [];
    if(!selectIsEmpty("order-panel-one-series-select") || !selectIsUnselected(orderPanelOneSeriesSelect)){
        orderPanelOneTitle.innerHTML = "Select " + orderPanelOneSeriesSelect.value.toString().toUpperCase() + " Option";
    }
    //on change we need to populate option select based on this value
    //now we need to get the particular series doc and fill get array then prmise all to get all options

    familyuid = getRecordFromList(doc.getElementById("order-panel-one-family-select"),orderPanelOneFamilySelect.selectedIndex);
    seriesuid = getRecordFromList(doc.getElementById("order-panel-one-series-select"),orderPanelOneSeriesSelect.selectedIndex);
    optionuid = getRecordFromList(doc.getElementById("order-panel-one-option-select"),orderPanelOneOptionsSelect.selectedIndex);
    optionRef = db.collection("products").doc(familyuid).collection("option");
    itemRef = db.collection("products").doc(familyuid).collection("item");
    targetRef = db.collection("products").doc(familyuid).collection("option").doc(optionuid);
    try {
        targetRef.get().then(function(snap) {
            if (snap.exists) {
                for (var key in snap.data()) {
                    if (snap.data().hasOwnProperty(key)) {
                        fetchPromise = itemRef.doc(key).get();
                        fetchArray.push(fetchPromise);
                    }
                }
                Promise.all(fetchArray).then(function(values) {
                    populateSelectFromQueryValues(values,"order-panel-one-item-select");
                    if(!selectIsEmpty("order-panel-one-item-select")){
                        enableSelect("order-panel-one-item-select");
                    }
                    targetRef.get().then(function(snap){
                        if(snap.data().name){
                            var str = snap.data().name.toString();
                            orderAsideInfo.innerHTML = "Select " + capitalizeFirstLetter(str) + " item.";
                        }
                    });
                });
            }
        }).catch(function(error) {
            toast("error check console");
            console.log("Error getting document:", error);
        });
    }

enter image description here