Mongodb按两个字段中的任何一个排序

时间:2014-11-22 18:09:22

标签: node.js mongodb sorting mongoose

有没有办法在mongodb中同时按两个字段排序? 所以我们假设我们在集合中有以下文档:

{ id: 'name1', last_1: 5, last_2: 2 },
{ id: 'name2', last_1: 1, last_2: 9 },
{ id: 'name3', last_1: 4, last_2: 3 }

我希望它按降序排序,检查last_1和last_2,结果将是: document2(last_2中的9),document1(last_1中的5),document3(last_1中的4)。我还需要知道它在结果中的哪个字段。 我目前的聚合看起来像这样:

{ $group:
      { _id: { id: '$name' },
        last_1: { $last: '$field1' },
        last_2: { $last: '$field2' },
      }
      },
      { $sort : { /* don't know what to put in here */ } },
      { $limit: some_limit }

UPD:我可能必须完全删除排序/限制并使用一些自定义节点功能,因为看起来我只能使用mongo来实现它,特别是因为额外的要求是列出如果两个字段的字段都大于其他文档,则同一文档两次。

3 个答案:

答案 0 :(得分:3)

也许是这样的,

1

db.test.aggregate([
    {$project: {name: 1, field1: 1, field2: 1}},
    {$group: {_id: '$name', field_1: { $last: '$field1' }, field_2: { $last: '$field2' }}},
    {$project: {name: 1, field_1: 1, field_2: 1, cmp: { $cmp: ['$field_2', '$field_1'] } }},
    {$sort: { cmp: -1, field_1: -1, field_2: -1 }}
])

2

db.test.aggregate([
    {$project: {name: 1, field1: 1, field2: 1}},
    {$group: {_id: '$name', field_1: { $last: '$field1' }, field_2: { $last: '$field2' }}},
    {$project: {
        name: 1, 
        field_1: 1, 
        field_2: 1, 
        largest: { $cond: [ {$gt: ['$field_2', '$field_1']}, '$field_2', '$field_1'] }    
    }},
    {$sort: { largest: -1 }}
])

答案 1 :(得分:1)

您要求sort根据字段last_1last_2last_1您的文档进行汇总,其中最大的字段可以汇总如下:

  • 投放一个额外字段,其中包含last_2sort中较大的值 descending
  • 根据此字段project db.collection.aggregate([ {$project:{"id":"$id", "last_1":1, "last_2":1, "sortField":{$cond:[ {$gt:["$last_1","$last_2"]}, "$last_1", "$last_2"]}}}, {$sort:{"sortField":-1}}, {$project:{"_id":0, "id":"$id", "last_1":1, "last_2":1}} ]) 订单中的记录。
  • 然后{{1}}必填字段。

汇总代码:

{{1}}

答案 2 :(得分:0)

好吧,这就是它结束的原因,我担心与mongodb-native相比它会变得太慢,但实际上并没有那么糟糕:

Test.aggregate(
        [
          { $match:
          {'modified': { $gte: settings.period } }
          },

          { $group:
          { _id: { name: '$name' },
            last_1: { $last: '$field_1' },
            last_2: { $last: '$field_2' },
          }
          }
        ],

        function (err, result) {
          if (err) callback(err);
          else {
            var arr = [];
            for (var i = 0; i < result.length; i++) {
              var obj = result[i];
              arr.push({ id: obj._id, sort: obj.last_1 });
              arr.push({ id: obj._id, sort: obj.last_2 });
            }
            arr.sort(compare).reverse();
            arr = arr.slice(0, settings.limit);
            var arr2 = [];
            for (i = 0; i < arr.length; i++) {
              var id = arr[i].id;
              var element = result.filter(function(element) {
                return element._id == id;
              });
              arr2.push(element[0]);
            }
            callback(null, arr2);
          }
        });
      );

function compare(a, b) {
  if (a.sort < b.sort)
    return -1;
  if (a.sort > b.sort)
    return 1;
  return 0;
}