如何删除Firestore中作为数组元素的map内部的指定字段?
问题根因
你要删除的varToDelete字段是嵌套在文档根字段loc的数组元素内部的,但是你写的更新路径直接指定了根级的varToDelete,和实际字段路径不匹配,所以删除指令没有命中目标字段,自然不会产生效果。
同时你在循环中多次调用事务的update方法也没有必要,所有字段更新可以合并为一次调用完成。
方案1:按数组下标删除对应字段(适合数组规模小、并发修改概率低的场景)
通过构造带数组下标的字段路径,精准定位要删除的嵌套字段:
await db.runTransaction(async (t) => { const locRef = db.collection('documents').doc('123-456'); const locSnapshot = await t.get(locRef); // 事务内读要使用事务对象的get方法,保证一致性 const loc = locSnapshot.data().loc; const updateData = {}; loc.forEach((item, index) => { if (typeof item.varToDelete !== 'undefined') { // 构造嵌套路径:loc.数组下标.varToDelete updateData[`loc.${index}.varToDelete`] = admin.firestore.FieldValue.delete(); } }); // 所有更新合并为一次事务调用 if (Object.keys(updateData).length > 0) { t.update(locRef, updateData); } });
注意:如果在你读取loc之后到事务提交前,有其他请求修改了loc数组的结构(比如新增/删除了数组元素),数组下标会发生偏移,可能导致删错字段,这种场景推荐使用下面的方案2。
方案2:重写整个loc数组(并发安全,通用性更强)
直接在内存中修改你读取到的loc数组,删除所有元素的varToDelete字段后,把整个数组更新回文档,事务会自动处理并发冲突,保证修改正确性:
await db.runTransaction(async (t) => { const locRef = db.collection('documents').doc('123-456'); const locSnapshot = await t.get(locRef); const loc = locSnapshot.data().loc; // 处理数组,删除每个元素的varToDelete字段 const processedLoc = loc.map(item => { const { varToDelete, ...rest } = item; return rest; }); t.update(locRef, { loc: processedLoc }); });
内容的提问来源于stack exchange,提问作者Icare
相关产品推荐
相关产品推荐

