我有一个"订单"集合,如下所示:
{ 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" }
)
希望它有帮助