2014-11-22 103 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