Firestore v9 如何更新数组内指定对象字段且不覆盖其他数据
Firestore v9 更新数组指定下标元素的嵌套字段方法
直接使用apps.0.points点语法更新时丢失其他字段,是Firestore数组更新的默认逻辑导致的:该写法会将数组下标0对应的整个元素替换为仅包含points属性的对象,同元素下的id、name字段会被直接清除,不属于语法错误。
不需要采用先删除再插入元素的繁琐方案,以下两种是生产环境可用的正确实现:
方案1:读取现有数组修改后整体回写(最通用,无兼容问题)
适合绝大多数场景,不会出现误删字段、误删重复元素的问题,代码实现如下:const db = getFirestore(); const ref = doc(db, 'users', uid); const matches = await getDoc(ref); if (!matches.exists()) return; // 浅拷贝现有apps数组,避免直接修改原数据 const appList = [...matches.data().apps]; // 仅修改目标下标元素的points字段,其余字段完整保留 appList[0] = { ...appList[0], points: 50 }; // 回写更新后的数组 return updateDoc(ref, { apps: appList });方案2:使用Firestore原子操作更新(无需全量覆盖数组)
如果你希望用数据库原生原子操作完成更新,可以组合arrayRemove和arrayUnion实现,前提是你能拿到目标下标元素的完整原始值:import { arrayRemove, arrayUnion } from "firebase/firestore"; const db = getFirestore(); const ref = doc(db, 'users', uid); const matches = await getDoc(ref); if (!matches.exists()) return; const oldTargetApp = matches.data().apps[0]; return updateDoc(ref, { apps: arrayRemove(oldTargetApp), apps: arrayUnion({ ...oldTargetApp, points: 50 }) });
注意:方案2存在使用限制,如果你的
apps数组中存在和oldTargetApp完全相同的重复元素,arrayRemove会把所有匹配的重复元素一并删除,存在重复元素的场景请优先使用方案1。
内容的提问来源于stack exchange,提问作者OSMX
相关产品推荐
相关产品推荐

