如何通过objectId更新嵌套文档中alt_names的is_used.hr属性值
MongoDB嵌套数组子字段更新方法
你描述的是MongoDB中嵌套两层数组的文档更新场景,优先推荐使用MongoDB 3.6及以上版本支持的arrayFilters实现精准定位更新,不需要提前查询数组索引,并发安全更高。
推荐更新语句
替换以下占位符后执行即可:
<顶层文档_id>:你要操作的最外层文档的_id值<目标alt_names子项_id>:待更新的alt_names子文档对应的_id值
db.collection.updateOne( // 匹配顶层文档 { "_id": ObjectId("<顶层文档_id>") }, // 指定要更新的字段路径 { $set: { "names.$[nameItem].alt_names.$[altItem].is_used.hr": true } }, // 嵌套数组筛选规则 { arrayFilters: [ // 筛选包含目标alt子项的names数组元素 { "nameItem.alt_names._id": ObjectId("<目标alt_names子项_id>") }, // 精准匹配目标alt_names子项 { "altItem._id": ObjectId("<目标alt_names子项_id>") } ] } )
低版本兼容方案(MongoDB 3.6以下)
如果使用的是不支持arrayFilters的旧版本,需要先查询文档拿到对应的数组索引再执行更新,该方案存在并发修改错位的风险,仅作为兜底方案使用:
// 第一步:查询文档获取对应索引 const targetDoc = db.collection.findOne({ "_id": ObjectId("<顶层文档_id>") }); let nameArrIndex = -1; let altArrIndex = -1; targetDoc.names.forEach((nameElem, nIdx) => { const foundAltIdx = nameElem.alt_names.findIndex(altElem => altElem._id.equals(ObjectId("<目标alt_names子项_id>")) ); if (foundAltIdx !== -1) { nameArrIndex = nIdx; altArrIndex = foundAltIdx; } }); // 第二步:执行更新 if (nameArrIndex !== -1 && altArrIndex !== -1) { db.collection.updateOne( { "_id": ObjectId("<顶层文档_id>") }, { $set: { [`names.${nameArrIndex}.alt_names.${altArrIndex}.is_used.hr`]: true } } ) }
注意事项
- 如果你的_id是自定义字符串类型而非MongoDB默认的ObjectId类型,去掉代码中的
ObjectId()包裹,直接传入字符串即可 - 若需要更新所有符合条件的文档,将
updateOne替换为updateMany即可
内容的提问来源于stack exchange,提问作者Aravinda Rathnayake
相关产品推荐
相关产品推荐

