使用MongoDB 2.2+ 中的聚合框架有几种方法可以解决这个问题。
不幸的是,2.2.2 的聚合框架还不支持$slice
or 数组子集运算符,因此需要一些额外的操作。
注意:下面的示例使用mongo
shell,但应该可以直接转换为 PHP 驱动程序。
示例 #1:使用聚合框架提取两个匹配项(第一个和最后一个)
假设您不为每个分组获得哪两个元素而烦恼,您可以选择$first
and $last
:
db.cars.aggregate(
// Group by $L and find the first and last elements
{ $group: {
_id: '$L',
first: { $first: "$M" },
last: { $last: "$M" },
}},
// Add an extra $index for # of array elements
{ $project: {
first: 1,
last: 1,
index: { $const:[0,1] }
}},
// Split into document stream based on $index
{ $unwind: '$index' },
// Re-group data using conditional to create array
{ $group: {
_id: '$_id',
M: {
$push: { $cond:[ {$eq:['$index', 0]}, '$first', '$last'] }
}
}}
)
样本输出:
{
"result" : [
{
"_id" : "cars",
"M" : [
"wolkswagen",
"mercedes"
]
},
{
"_id" : "bike",
"M" : [
"bianchi",
"brook"
]
}
],
"ok" : 1
}
示例#2:使用聚合框架创建一个集合,然后减少
上述方法的替代方法是使用更简单的管道$addToSet
和后处理步骤来修剪数组元素:
var agg = db.cars.aggregate(
{ $group: {
_id: '$L',
'M': { $addToSet: "$M" },
}}
)
// Iterate to trim each result to the desired # of elements
agg.result.forEach(function(doc) {
// Note: you could randomly select 2 (or n) elements here
doc.M = doc.M.slice(0,2);
})
输出格式将与示例 #1 相同,但示例 #2(如所写)选择前两个元素,而不是选择第一个和最后一个元素。