如何获取数组内元素的索引?MongoDB聚合与$map使用遇阻
给MongoDB数组元素添加索引属性的解决方案
不管是聚合排序后还是用$map遍历,MongoDB都没有内置方式直接获取数组元素的索引,这里提供两种实用解决办法:
1. 用$zip + $range生成带索引的数组
通过$range生成从0开始的连续数字序列(长度和目标数组一致),再用$zip把原数组和索引序列配对,最后用$map遍历配对结果,把索引作为新属性合并到元素中。
示例:给简单数组添加索引
假设集合中有这样的文档:
{ "_id": 1, "fruits": ["apple", "banana", "cherry"] }
执行以下聚合管道:
db.collection.aggregate([ { $addFields: { fruitsWithIndex: { $map: { input: { $zip: { inputs: ["$fruits", { $range: [0, { $size: "$fruits" }] }] } }, as: "pair", in: { value: { $arrayElemAt: ["$$pair", 0] }, index: { $arrayElemAt: ["$$pair", 1] } } } } } } ])
生成的fruitsWithIndex数组会是:
[ { "value": "apple", "index": 0 }, { "value": "banana", "index": 1 }, { "value": "cherry", "index": 2 } ]
示例:给对象数组添加索引
如果原数组元素是对象,用$mergeObjects直接合并索引属性即可:
db.collection.aggregate([ { $addFields: { itemsWithIndex: { $map: { input: { $zip: { inputs: ["$items", { $range: [0, { $size: "$items" }] }] } }, as: "pair", in: { $mergeObjects: [ { $arrayElemAt: ["$$pair", 0] }, { index: { $arrayElemAt: ["$$pair", 1] } } ] } } } } } ])
2. 排序后添加索引
如果需要先对数组排序再添加索引,先通过$sortArray完成排序,再重复上面的$zip + $map流程:
假设原文档是:
{ "_id": 1, "products": [ { "name": "banana", "price": 2 }, { "name": "apple", "price": 1 }, { "name": "cherry", "price": 3 } ] }
排序并添加索引的聚合管道:
db.collection.aggregate([ { $addFields: { sortedProducts: { $sortArray: { input: "$products", sortBy: { price: 1 } } } } }, { $addFields: { sortedProductsWithIndex: { $map: { input: { $zip: { inputs: ["$sortedProducts", { $range: [0, { $size: "$sortedProducts" }] }] } }, as: "pair", in: { $mergeObjects: [ { $arrayElemAt: ["$$pair", 0] }, { index: { $arrayElemAt: ["$$pair", 1] } } ] } } } } } ])
最终sortedProductsWithIndex里的元素会按价格排序,并且带有正确的索引值。
为什么直接用$map拿不到索引?
MongoDB的$map遍历过程中,每个元素变量(比如$$this)只包含元素本身的数据,没有内置的index属性。必须手动生成索引序列并和原数组绑定,才能给元素添加索引属性。
内容的提问来源于stack exchange,提问作者Patrick Marlon
相关产品推荐
相关产品推荐

