MongoDB单更新查询清理嵌套数组:移除缺失指定字段的对象
MongoDB 深层嵌套数组清理的单更新查询方案
需求:通过单个更新查询,移除_a._p.s.[a|c|d].t中缺失did、dst和den字段的对象,同时保证不存在_a._p.s的_a._p对象内容不受破坏。
现有方案缺陷:
- 某方案在不存在
_a._p.s时,会破坏_a._p的原有内容 - 另一方案在
_a._p.s下缺失a/c/d对象时,会自动添加null值对象,不符合预期
原始示例文档
[ { "_id": ObjectId("5c05984246a0201286d4b57a"), "f": "x", "_a": [ { "_onlineStore": {} }, { "_p": { "s": { "a": { "t": [ { "id": 1, "dateP": "20200-09-20", "did": "x", "dst": "y", "den": "z" }, { "id": 2, "dateP": "20200-09-20" } ] }, "c": { "t": [ { "id": 3, "dateP": "20300-09-22" }, { "id": 4, "dateP": "20300-09-23", "did": "x", "dst": "y", "den": "z" }, { "id": 5, "dateP": "20300-09-23" } ] } } } } ] }, { "_id": ObjectId("5c05984246a0201286d4b57b"), "f": "x", "_a": [ { "_onlineStore": {} }, { "_p": { "_t": "Some field", "_x": "Some other field" } } ] } ]
更新后预期结果
[ { "_id": ObjectId("5c05984246a0201286d4b57a"), "f": "x", "_a": [ { "_onlineStore": {} }, { "_p": { "s": { "a": { "t": [ { "id": 1, "dateP": "20200-09-20", "did": "x", "dst": "y", "den": "z" } ] }, "c": { "t": [ { "id": 4, "dateP": "20300-09-23", "did": "x", "dst": "y", "den": "z" } ] } } } } ] }, { "_id": ObjectId("5c05984246a0201286d4b57b"), "f": "x", "_a": [ { "_onlineStore": {} }, { "_p": { "_t": "Some field", "_x": "Some other field" } } ] } ]
解决方案:单更新查询
db.collection.updateMany( {}, [ { $set: { "_a": { $map: { input: "$_a", as: "aItem", in: { $cond: [ { $ne: ["$$aItem._p", undefined] }, { $mergeObjects: [ "$$aItem", { "_p": { $cond: [ { $ne: ["$$aItem._p.s", undefined] }, { $mergeObjects: [ "$$aItem._p", { "s": { $arrayToObject: { $map: { input: { $objectToArray: "$$aItem._p.s" }, as: "sEntry", in: { $cond: [ { $in: ["$$sEntry.k", ["a", "c", "d"]] }, { k: "$$sEntry.k", v: { "t": { $filter: { input: "$$sEntry.v.t", as: "tItem", cond: { $and: [ { $ne: ["$$tItem.did", undefined] }, { $ne: ["$$tItem.dst", undefined] }, { $ne: ["$$tItem.den", undefined] } ] } } } } }, "$$sEntry" ] } } } } } ] }, "$$aItem._p" ] } } ] }, "$$aItem" ] } } } } } ] )
方案说明
- 精准过滤目标元素:通过
$filter对s.[a|c|d].t数组筛选,仅保留同时包含did、dst、den三个字段的对象 - 避免破坏非目标对象:多层
$cond判断确保仅当_p.s存在时才修改该结构,无s的_p对象完全保留原有内容 - 防止添加null值:用
$objectToArray+$map遍历s下的键值对,仅处理a/c/d键,其他键直接保留,不存在的键不会被新增null值
内容的提问来源于stack exchange,提问作者R2D2
相关产品推荐
相关产品推荐

