如何聚合集合并查找最小值/最大值



我有一个"订单"集合,如下所示:

{ typeID: 1, buyOrder: true, price: 100 },
{ typeID: 1, buyOrder: false, price: 120 },
{ typeID: 1, buyOrder: false, price: 130 },
{ typeID: 1, buyOrder: false, price: 250 },
{ typeID: 2, buyOrder: true, price: 500 },
{ typeID: 2, buyOrder: false, price: 610 },
{ typeID: 2, buyOrder: false, price: 690 },
{ typeID: 2, buyOrder: false, price: 590 }

我想汇总这个集合并为每个类型id找到最佳买入/卖出价格。

结果应该是:

{ typeID: 1, bestBuy: 100, bestSell: 120 }
{ typeID: 2, bestBuy: 500, bestSell: 610 }

定义最佳购买/最佳销售

bestBuy  = (buyOrder = true && max price)
bestSell = (buyOrder = false && min price)

这就是我到目前为止所拥有的,但我知道这是错误的。有什么想法吗?

db.orders.aggregate([
    { $sort : { typeID : 1 }},
    { $group: 
        { _id: { typeID : "$typeID", buyOrder : "$buyOrder"},
        price: { $max: "$price" },
        }
     },
     { $project:
         { _id: 0,
             typeID: "$_id.typeID",
             price: "$price",
             buyOrder: "$_id.buyOrder",
         }
     }
    ])

谢谢你的时间。

您可能还不知道作为三元条件工作的$cond运算符。所以基本上,如果给定 a 作为第一个参数的条件是true那么在下一个参数中使用该值。如果条件的计算结果为 false则使用运算符中最后一个条件中的值。

事实证明这是完美的,因为您已经有一个真或假的指标来确定字段

db.orders.aggregate([
    { "$project": {
        "typeID": 1,
        "bestBuy": { "$cond": [
            "$buyOrder",
            "$price",
            null
        ]},
        "bestSell": { "$cond": [
            "$buyOrder",
            null,
            "$price"
        ]}
    }},
    { "$group": {
        "_id": "$typeID",
        "bestBuy": { "$max": "$bestBuy" },
        "bestSell": { "$min": "$bestSell" }
    }},
    { "$sort": { "_id": 1 } }
])

因此,在此处使用 $max $min 可以否定未满足条件的结果中的null值。

也许使用mapreduce,你可以用这样的东西来实现这一点:

var mapFunction1 = function() {
 emit(this.typeID , this.buyOrder, this.price);
};
var reduceFunction1 = function(key, values) {
 reducedValue = { bestBuy: 0, bestSell: 0 };
 for (var idx = 0; idx < values.length; idx++) {
  if(values[idx].buyOrder && reducedValue.bestBuy < values[idx].price) {
   reducedValue.bestBuy = values[idx].price
  }
  if(!values[idx].buyOrder && reducedValue.bestSell > values[idx].price) {
   reducedValue.bestSell = values[idx].price
  }
 }
 return reducedValue;
};
db.orders.mapReduce(
 mapFunction1,
 reduceFunction1,
 { out: "your_result" }
)

希望它有帮助

相关内容

  • 没有找到相关文章

最新更新