Mongodb聚合操作如何筛选数组中索引为12的倍数的元素
具体实现方案
$filter原生无法直接获取数组元素的索引,针对你的需求有两种可行实现方式,其中第二种性能更优:
方案1:基于$filter实现
需要先将数组元素和对应索引绑定后再做过滤:
db.test.aggregate([ { $project: { filtered_values: { $filter: { input: { $zip: { inputs: [ // 生成和数组长度一致的连续索引序列 { $range: [0, { $size: "$data" }] }, "$data" ] } }, as: "item", // 筛选索引为12倍数的元素 cond: { $eq: [ { $mod: [ { $arrayElemAt: [ "$$item", 0 ] }, 12 ] }, 0 ] } } } }, // 去除索引,仅保留元素值 { $project: { filtered_values: { $map: { input: "$filtered_values", as: "item", in: { $arrayElemAt: [ "$$item", 1 ] } } } } } ])
方案2:更高效的索引直接取值方案(推荐)
无需遍历所有数组元素,直接生成所有符合要求的索引后取值,对于5000+元素的大数组性能提升非常明显:
db.test.aggregate([ { $project: { filtered_values: { $map: { // 直接生成步长为12的索引序列:0、12、24...直到数组末尾 input: { $range: [0, { $size: "$data" }, 12] }, as: "idx", // 直接取出对应索引的元素 in: { $arrayElemAt: [ "$data", "$$idx" ] } } } } } ])
方案对比
$filter并不是该场景的最优解决方案:
- $filter方案需要遍历所有数组元素,还要额外做索引绑定、两次投影操作,资源开销更高。
- 直接生成目标索引取值的方案,仅需要遍历原数组1/12数量的元素,执行效率高很多,更适合大数组场景。
以上方案兼容MongoDB 3.2及以上版本。
内容的提问来源于stack exchange,提问作者Rafael Barlera
相关产品推荐
相关产品推荐

