说我有类似下面的文件:
{
email: "test@test.com",
values: [2,9]
},
{
email: "test@test.com",
values: [1,3]
},
{
email: "another@email.com",
values: [4,5]
},
我希望为每封电子邮件获取values
数组中第一个元素的最大值(2
为test@test.com
。是否可以应用{{1} }只到数组的第一个元素?我尝试了下面的方法:
$max
和
db.test.aggregate({$group:{_id: '$email', max: {$max: "$values[0]"}}})
但似乎都不起作用(它们返回db.test.aggregate({$group:{_id: '$email', max: {$max: "$values.0"}}})
或null
的空数组。可以这样做吗?
答案 0 :(得分:2)
关闭try,但遗憾的是聚合框架无法使用.find()
等方法可用的标准投影形式。你需要更多参与才能获得你想要的东西。
db.test.aggregate([
// Unwind the arrays
{ "$unwind": "$values" },
// Get the first value out of each document. Yes, order is respected.
{ "$group": {
"_id": "$_id",
"email": { "$first": "$email" },
"firstValue": { "$first": "$values" }
}},
// Then get "max" per grouping key
{ "$group": {
"_id": "$email",
"value": { "$max": "$firstValue" }
}}
])
这是有效的,因为$first
拉出"第一个"匹配"分组边界"并且在展开数组内容时会遵守数组的顺序。
所以"首先" $group
阶段获得"第一个"文档中的数组元素。 "第二" $group
阶段一旦提取完就会对所有这些值执行$max
。
P.S。不要问如何获得" nth"这个价值完全是另一个问题,而且涉及的更多。如果你遵循它,那么有一个合乎逻辑的进展。它不是最佳解决方案,但可以做到。
相信我,因为我们一直在寻找"切片"预测和"限制"在$push
操作已有一段时间了。它可能会在某一天发生。
答案 1 :(得分:1)
我建议使用更简洁,更通用的解决方案,适用于任何数组索引:
db.test.aggregate([
{$project: {email: "$email", first_value:
{$arrayElemAt: [ "$values", 0]}}},
{$group: {_id: '$email', value: {$max: '$first_value'}}}
])