SailsJS& MongoDB聚合框架遇到自定义查询的麻烦 [英] SailsJS & MongoDB Aggregation framework troubles with custom queries

查看:49
本文介绍了SailsJS& MongoDB聚合框架遇到自定义查询的麻烦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对MongoDB完全陌生,来自SQL背景.

I'm totally new to MongoDB and come from an SQL background.

我正在尝试这样做:

Get the top Artists, based on the number of Dubs.

数据结构:

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
}]

我试图:

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);
  });
});

哪个给我

[]

然后:

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);
  });
});

哪个给我

[ { _id: 'The Beatles', total: 1 },
{ _id: 'The Doors', total: 1 } ]

谢谢

推荐答案

您的第一个查询是在使用错误的管道运算符的正确轨道上进行的.

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);
        }
})

当然 $size 运算符要求您需要一个MongoDB 2.6或更高版本,您可能现在应该这样做,但是如果没有运算符来测量数组长度,您仍然可以做到这一点:

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:

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);
        }
})

这通过计数数组的成员来完成相同的操作,但是您需要 $unwind 数组元素以对其进行计数.因此它仍然可以完成,但效率不高.

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. So it can still be done but is not as efficient.

此外,由于 $ifNull > 设置一个数组,其中文档甚至不包含 $unwind 不会导致错误.

Additionally you need to handle the cases where the array is truly blank but present because of how $unwind treats an empty array []. 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.

真的,如果您打算定期进行这种查询,则应在文档中保留一个总计"字段,而不要首先进行计算.使用 $inc 运算符使用 $push 之类的操作和 $pull 来保持当前数组长度的计数.

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.

这确实偏离了一般的Waterline理念,但是您已经引入了本机聚合操作,要了解通过在其他领域中使用本机操作也可以获得更好的性能,这并不是一件容易的事.

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.

对于这样的文档:

{
  "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
}

这篇关于SailsJS& MongoDB聚合框架遇到自定义查询的麻烦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆