假设我有这样的结构:
items: {
id1: {
likes: 123
},
id2: {
likes: 456
},
id3: {
sourceId: 'id1',
likes: 123
},
id4: {
sourceId: 'id1',
likes: 123
}
[,...]
}
其中任何项目可以是源项目或引用源项目的项目。引用源项目的目的是使所有共享相同sourceId的项目的计数器保持一致。
因此,当我更改源项目的计数器时,我想将该计数器的值批量写入所有具有该项目作为其sourceId的项目。
假设我在引用某些sourceId的文档中读取,然后我将批量更改提交给所有这些文档。如果批量文档中的一小部分文档在读入文档后的小窗口中被删除,或者发生了罕见但可能的写入速率冲突,该怎么办?没有计数器更新,因为1或2个文档无法更新?
是否可以提交一个批处理,独立地将更改写入每个文档,如果一个文档失败,它对其他文档是否写入没有影响?
或者对于这种情况,最好在引用某些sourceId的文档中读取,然后并行地将更改写入每个文档,以实现写入独立性。 我不喜欢这种方法,因为请求数量就是批量的大小。
你有什么想法?
答案 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);
});
}