2014-11-22 73 views
0

有没有一种方法可以在mongodb中同时按两个字段排序? 所以我们可以说,我们有集合中的下列文件: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进行排序,那么结果将是: 书2(在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,尤其是因为如果两个字段的字段都比其他文档中的字段大,那么额外的要求是将同一个文档列出两次。

+0

如果没有您自己的输入,在这种情况下应优先选择哪个字段几乎是不可能的。因此,目前唯一的方法是通过聚合框架为单个排序字段分配权重到这些字段。 – Sammaye 2014-11-22 18:53:04

+0

它们都不应该优先考虑,在小组阶段之后,我再说一次,比如5个文档,最后一个值是两个字段我希望mongo在排序后根据前5个值对所有10个值(5个文档* 2个最后的值)进行排序并排列这些文档。 – 2014-11-22 19:15:06

+0

好吧,在你的例子中,doc 2应该以last_2为优先,因为那是9,而doc1应该以last_1为优先,因为那是5,还是我误会了? – Sammaye 2014-11-22 21:23:37

回答

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, cmp: { $cmp: ['$field_2', '$field_1'] } }}, 
    {$sort: { cmp: -1, field_1: -1, field_2: -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, 
     largest: { $cond: [ {$gt: ['$field_2', '$field_1']}, '$field_2', '$field_1'] }  
    }}, 
    {$sort: { largest: -1 }} 
]) 
1

你的要求是基于田间地头,last_1last_2集合中sort您的文件为准其中最大的可以汇总如下:

  • 投射一个额外的字段,其中保存较大的值last_1last_2
  • 基于此字段sort记录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}} 
]) 
+0

好的变体,我刚刚重写了查询和更新的例子.. +1从我的 – 2014-11-23 08:08:31

0

好了,这是怎么结束了,我害怕它会是与一些MongoDB的原生比较太慢,但它实际上不是那么糟糕:

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; 
} 
+0

'mongodb native'是什么意思?您已经完成了客​​户端的所有工作。当你可以在服务器端做到这一点时,不是这样做的。 – BatScream 2014-11-23 21:31:35

+0

@BatScream,这是我的服务器端。 – 2014-11-23 21:49:28

+0

没有它没有。你已经处理了回调函数中的所有内容。 – BatScream 2014-11-23 21:50:22