[英]SailsJS & MongoDB Aggregation framework troubles with custom queries
I'm totally new to MongoDB and come from an SQL background. 我对MongoDB完全陌生,来自SQL背景。
I'm trying to do this : 我正在尝试这样做:
Get the top Artists, based on the number of Dubs.
Data Structure : 数据结构 :
Artists = [
{
"dubs": [{...},{...},{...}],
"name": "The Doors",
"createdAt": "2014-12-15T15:24:26.216Z",
"updatedAt": "2014-12-15T15:24:26.216Z",
"id": "548efd2a436c850000353f4f"
},
{
"dubs": [],
"name": "The Beatles",
"createdAt": "2014-12-15T20:30:33.922Z",
"updatedAt": "2014-12-15T20:30:33.922Z",
"id": "548f44e90630d50000e2d61d"
},
{...}
]
So the result I seeking for would be something like this : 所以我想要的结果将是这样的:
[{
_id: "548ef6215755950000a9a0de",
name:"The Doors",
total: 3
},{
_id: "548ef6215715300000a9a1f9",
name:"The Beatles",
total: 0
}]
I tried to : 我试过了 :
Artist.native(function(err, collection) {
collection.aggregate([ {
$group: {
_id: {
name: "$name"
},
total: {
$size: "$dubs"
}
}
}, {
$size: {
total: -1
}
}], function(e, r) {
if (e) res.serverError(e);
console.log(r);
});
});
Which gives me 这给了我
[]
And : 和:
Artist.native(function(err, collection) {
if (err) return res.serverError(err);
collection.aggregate({
$group: {
_id: "$name",
total: {
$sum: 1
}
}
}, {
$sort: {
total: -1
}
}, function(e, r) {
console.log(r);
if (e) return res.serverError(e);
});
});
Which gives me 这给了我
[ { _id: 'The Beatles', total: 1 },
{ _id: 'The Doors', total: 1 } ]
Thanks 谢谢
Your first query was on the right track back you were using the the wrong pipeline operator. 您的第一个查询是在使用错误的管道运算符的正确轨道上进行的。
Artist.native(function(err,collection) {
collection.aggregate(
[
{ "$project": {
"_id": 1,
"name": 1,
"total": { "$size": "$dubs" }
}}
],
function(err,result) {
if (err) return res.serverError(err);
console.log(result);
}
})
Of course the $size
operator there requires that you need a MongoDB 2.6 or greater version, which you probably should do by now, but you can still to the same thing without the operator for measuring the array length: 当然,那里的
$size
运算符要求您需要一个MongoDB 2.6或更高版本,您可能现在应该这样做,但是如果没有该运算符来测量数组长度,您仍然可以做到这一点:
Artist.native(function(err,collection) {
collection.aggregate(
[
{ "$project": {
"_id": 1,
"name": 1,
"dubs": {
"$cond": [
{ "$eq": [ "$dubs", [] ] },
[0],
"$dubs"
]
}
}},
{ "$unwind": "$dubs" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"total": {
"$sum": {
"$cond": [
{ "$eq": [ "$dubs", 0 ] },
0,
1
]
}
}
}}
],
function(err,result) {
if (err) return res.serverError(err);
console.log(result);
}
})
That does the same thing by counting the members of the array, but instead you would need to $unwind
the array elements in order to count them. 通过对数组的成员进行计数可以达到相同的目的,但是您需要对数组元素进行
$unwind
以对其进行计数。 So it can still be done but is not as efficient. 因此它仍然可以完成,但效率不高。
Additionally you need to handle the cases where the array is truly blank but present because of how $unwind
treats an empty array []
. 另外,由于
$unwind
如何处理空数组[]
您需要处理数组确实为空但存在的情况。 If there was no content then the document that contained such an element would be removed from the results. 如果没有内容,则将从结果中删除包含此类元素的文档。 In a similar way you would need to use
$ifNull
to set an array where the document did not even contain an element for $unwind
to not result in an error. 以类似的方式,您将需要使用
$ifNull
设置一个数组,其中文档甚至不包含$unwind
的元素以免导致错误。
Really if you intend to do this kind of query on a regular basis, then you should maintain a "total" field in the document rather than seek to calculate it first. 确实,如果您打算定期进行这种查询,那么您应该在文档中维护一个“总计”字段,而不是先进行计算。 Use the
$inc
operator along with operations such as $push
and $pull
to keep a tally of the current array length. 将
$inc
运算符与$push
和$pull
等操作配合使用,以保持当前数组长度的计数。
That does move away from the general Waterline philosophy a bit, but you have already introduced native aggregation operations and it's not that much more of a stretch to realize you are getting better performance from using native operations in other areas as well. 这确实偏离了一般的Waterline理念,但是您已经引入了本机聚合操作,并且意识到在其他领域使用本机操作也能获得更好的性能并不是一件容易的事。
So with documents like these: 因此,使用以下文档:
{
"dubs": [{},{},{}],
"name": "The Doors",
"createdAt": "2014-12-15T15:24:26.216Z",
"updatedAt": "2014-12-15T15:24:26.216Z",
"id": "548efd2a436c850000353f4f"
},
{
"dubs": [],
"name": "The Beatles",
"createdAt": "2014-12-15T20:30:33.922Z",
"updatedAt": "2014-12-15T20:30:33.922Z",
"id": "548f44e90630d50000e2d61d"
}
You get exactly the results you want in each case: 在每种情况下,您都能获得所需的结果:
{
"_id" : ObjectId("5494b79d7e22da84d53c8760"),
"name" : "The Doors",
"total" : 3
},
{
"_id" : ObjectId("5494b79d7e22da84d53c8761"),
"name" : "The Beatles",
"total" : 0
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.