MongoDB使用$slice对嵌套数组切片时如何仅返回匹配的目标元素
MongoDB嵌套数组过滤+切片解决方案
问题原因
原有写法的问题在于:find查询的投影操作仅对datapoints执行了切片,没有过滤外层datasets数组中不符合条件的元素,因此会返回所有datasets成员,且每个成员的datapoints都会被执行切片操作。
要实现同时过滤外层匹配元素+切片内层数组,需要使用MongoDB聚合管道实现,推荐两种实现方案:
方案1:低版本兼容写法(支持MongoDB 3.2+)
db.collection.aggregate([ // 第一步:过滤符合条件的根文档,缩小查询范围 { $match: { name: "admin", "datasets.name": "test" } }, // 第二步:拆解datasets数组为单条独立文档 { $unwind: "$datasets" }, // 第三步:仅保留datasets.name为test的匹配条目 { $match: { "datasets.name": "test" } }, // 第四步:投影出目标结构,同时对datapoints执行切片 { $project: { _id: 0, datapoints: { $slice: ["$datasets.datapoints", 0, 4] } } } ])
方案2:高性能简洁写法(支持MongoDB 4.4+)
无需拆分数组,直接通过$filter过滤匹配元素,性能更优:
db.collection.aggregate([ { $match: { name: "admin", "datasets.name": "test" } }, { $project: { _id: 0, datapoints: { $slice: [ // 过滤出datasets中name为test的第一个元素 { $getField: { input: { $first: { $filter: { input: "$datasets", cond: { $eq: ["$$this.name", "test"] } } } }, field: "datapoints" } }, 0, 4 ] } } } ])
运行结果
两种方案执行后都会返回你期望的结果:
{ "datapoints" : [ 1, 6, 4, 3 ] }
内容的提问来源于stack exchange,提问作者Ilijanovic
相关产品推荐
相关产品推荐

