【问题标题】:How to sort a MongoDB query for a ratio of two fields in every document?如何对每个文档中两个字段的比率对 MongoDB 查询进行排序?
【发布时间】:2011-02-24 20:52:02
【问题描述】:

假设我有很多文档,例如 {'a' : x , 'b' : y}。 假设 x 和 y 是整数。 我该怎么做find().sort({'a'/'b'}) 之类的事情?

【问题讨论】:

    标签: sorting mongodb mongodb-php


    【解决方案1】:

    自从 2011 年提出这个问题以来,MongoDB 已经发布了聚合框架。它允许您按字段组合进行排序,并且您不需要存储(非规范化)任何额外的字段。以下是它的完成方式:

    db.collection.aggregate([
    {
        $match: {
            // Optional criteria to select only some documents to process, such as...
            deleted: null
        }
    },
    {
        $project: {
            // Need to prefix fields with '$'
            ratio: { $divide: [ "$a", "$b" ] },
        }
    },
    {
        $sort: { ratio: -1 },
    }
    ]);
    

    就是这样。我们使用aggregation framework$divide 运算符。

    【讨论】:

      【解决方案2】:

      您可以添加第三个字段,a/b 的结果并按其排序。

      您的文档将如下所示:

      {'a' : x , 'b' : y, c : z} // z = x/y
      

      你会按'c'排序:

      find().sort({c : 1})
      

      【讨论】:

      • 有什么方法可以定义这个字段,每次 x 或 y 递增时,字段 c 都会更新它的值?
      • 不,没有其他方法(除了@AdaTheDev 所说的javascript函数,它会运行缓慢)。您可以在一次操作中递增和更新。
      • @JoãoPintoJerónimo:与此同时,MongoDB 已经发布了aggregation framework,因此ab 之间的比率可以即时计算。
      【解决方案3】:

      我不相信这是可能的,因为您也无法运行比较 2 个字段的查询(不使用 $where 来指定一个很慢的 javascript 函数)。相反,我怀疑您还需要将比率单独存储在文档中,然后按该新字段排序。

      【讨论】:

      【解决方案4】:

      就像 Bugai13 所说,您需要在您的集合中需要第三个属性才能执行排序。您可以通过调用 mapReduce 来添加 ratio 属性(如下所示),但这在大型集合上不会非常快 - 并且会在数据库运行时锁定您的数据库。你真的应该手动保持 ratio 属性是最新的——这应该不是很难。

      db.data.insert({a: 1, b: 1});
      db.data.insert({a: 2, b: 2});
      db.data.insert({a: 3, b: 3});
      db.data.insert({a: 1, b: 4});
      db.data.insert({a: 2, b: 1});
      db.data.insert({a: 3, b: 2});
      db.data.insert({a: 1, b: 3});
      db.data.insert({a: 2, b: 4});
      db.data.insert({a: 3, b: 1});
      db.data.insert({a: 1, b: 2});
      db.data.insert({a: 2, b: 3});
      db.data.insert({a: 3, b: 4});
      
      db.data.mapReduce(
          function(){
              emit(this._id, this);
          },
          function(k, vs){
              v = vs[0];
              v.c = v.a / v.b;
              return v;
          },
          {out : 'data'}
      );
      
      db.data.find().sort({c:1});
      

      【讨论】:

      猜你喜欢
      • 2019-03-30
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多