【问题标题】:Mongodb sort by either of two fieldsMongodb 按两个字段之一排序
【发布时间】:2015-01-20 17:48:41
【问题描述】:

有没有办法在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 来实现它,特别是因为附加要求是列出如果两个字段都大于其他文档,则同一文档两次。

【问题讨论】:

  • 在这种情况下,如果没有您自己的输入,几乎不可能分辨出哪个字段应该优先。因此,目前唯一的方法是通过聚合框架为单个排序字段的这些字段分配权重
  • 他们都不应该优先,再次,在小组赛之后,我有 5 个文档,两个字段的最后一个值,我希望 mongo 获取所有 10 个值(5 个文档 * 2 个最后values),对它们进行排序并根据排序后的前 5 个值排列这些文档。
  • 好吧,您在示例中说 doc 2 应该优先考虑 last_2 因为那是 9 而 doc1 应该优先考虑 last_1 因为那是 5,还是我弄错了?

标签: node.js mongodb sorting mongoose


【解决方案1】:

也许是这样的,

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

【讨论】:

    【解决方案2】:

    您的要求是根据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}}
    ])
    

    【讨论】:

      【解决方案3】:

      好的,结果就是这样,我担心它与 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;
      }
      

      【讨论】:

      • mongodb native 是什么意思?您最终在客户端完成了所有操作。当您可以在服务器端执行此操作时,这不是执行此操作的方法。
      • @BatScream,这是我的服务器端。
      • 不,不是。您已经处理了回调函数中的所有内容。
      • @BatScream,这是 nodejs,这是我的服务器代码,你在说什么客户端?
      • 我提到了数据库服务器而不是你的应用服务器。客户端我的意思是你的应用服务器。它是触发查询并充当数据库服务器的客户端。
      猜你喜欢
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多