我有一个mongodb / mongoskin聚合请求如下:
db.collection(customerTable + '_earnedinfluencers').aggregate([
{
$group: {
_id: '$user',
name: '', // to be filled separately
username: '', // to be filled separately
picture: '', // to be filled separately
city: '', // to be filled separately
kids: { $sum: '$kids' },
revenue: { $sum: '$dayIncome' },
kidsRevRatio: { $divide: [ { $sum: '$kids' }, { $sum: '$dayIncome' } ] }
},
$match: {
richness: { $gte: variable1 },
kids: { $lt: variable2 },
hobbies: { $in: ['hobby1', 'hobby2', 'hobby3', 'hobby4'] },
event: { $in: schoolfestival },
event: { $ne: 0 }
},
$project: {
_id: 0,
user: '$_id',
name: 1,
username: 1,
picture: 1,
city: 1,
kids: 1,
revenue: 1,
kidsRevRatio: 1
}
}
], function(err, result) {
// do something with err and result
});
上面的代码给出了以下错误:
Error: {"name":"MongoError","errmsg":"exception: A pipeline stage specification object must contain exactly one field.","code":16435,"ok":0}
我一般都是mongo和db的新手,并且无法说出我做错了什么。
答案 0 :(得分:11)
您的管道参数不平衡,每个阶段都是一个单独的文档,因此您需要将每个阶段包装起来。但是还有其他一些问题
db.collection(customerTable + '_earnedinfluencers').aggregate([
{ $match: {
richness: { $gte: variable1 },
kids: { $lt: variable2 },
hobbies: { $in: ['hobby1', 'hobby2', 'hobby3', 'hobby4'] },
event: { $in: schoolfestival },
}},
{ $group: {
_id: '$user',
name: { '$first': '$name' },
username: { '$first': '$username' },
picture: { '$first': '$picture' },
city: { '$first': '$city' }
kids: { '$sum': '$kids' },
revenue: { '$sum': '$dayIncome' },
kidsSum: { '$sum': '$kids' },
}},
{ $project: {
_id: 0,
user: '$_id',
name: 1,
username: 1,
picture: 1,
city: 1,
revenue: 1,
kidsSum: 1,
kidsRevRatio: { $divide: [ '$kidsSum', '$revenue' ] }
}}
], function(err, result) {
// do something with err and result
});
您将整个管道作为一个文档,实际上它需要一个显示的文档数组。
但是你真的要首先 $match
来过滤你的结果。如果你真的想在一个组之后进行一些额外的匹配,那么你之后会在管道中添加一个额外的匹配。
$group
操作要求_id
分组键之外的所有字段都需要有一个"分组运算符"除非他们是你所在的_id
成员的一部分,否则你不能仅仅依靠自己的领域。通常,您需要运营商,例如 $first
,或者完全省略它们。
仅限顶级分组运算符,因此 $divide
等操作不是分组运算符。为了在您使用一个或多个 $sum
结果时执行此类操作,请将其移至以后的 $project
具有计算值的字段。
此外,像项目和小组这样的操作,"删除"来自管道的字段,仅保留您特别包含的字段。因此,您无法指定不存在的字段。这是$match
首先出现的原因之一,也就是您可以使用索引的原因,并且只有在管道开始时才可以这样做。
但是对于每个阶段,唯一存在的字段将是那些提到的字段。作为进一步优化的优化者"从一开始就不包括文档中未提及的任何字段。因此,只有在第一个匹配和组合阶段中引用的那些将包含在其余的pipline阶段中,然后可能再次过滤掉。