在使用MongoDB时,我目前正在执行一个有条件的upsert作为聚合过程的一部分,其形式如下(大大简化):
db.dbname.update({attr1 : value1, attr2 : value2},
{"$inc" : { avg : current_value, nr : 1}},
false (multi), true (upsert))
但是我希望能够保留一个最大值(和最小值),而不必检索文档。类似于:
db.dbname.update({ attr1 : value1, attr2 : value2},
{"$inc" : { avg : current_value, nr : 1},
"$setIfBigger" : { max : current_value}},
false (multi), true (upsert))
有没有一种高效的方法可以实现这个功能?
我目前采用的方法非常低效,即检查是否存在当前的聚合文档,如果存在则相应地更新值,如果不存在则创建一个新文档。例如(再次说明,已经简化了很多,但本质在于此):
var obj = db.dbname.findOne({attr1 : value1, attr2 : value2},{_id:1});
if (obj != null) {
db.dbname.update({attr1 : value1, attr2 : value2},
{"$inc" : { avg : current_value, nr : 1},
"$set" : { max : (obj.max > current_value ? obj.max : current_value}},
false (multi), true (upsert));
} else {
db.dbname.save({attr1 : value1, attr2 : value2,
avg : current_value, nr : 1,
max : current_value});
}
实际程序是用Java编写并使用mongo-API,聚合过程相当复杂,使用的组合技术远超JavaScript与其他服务器通信,因此mapreduce不是选择。最终结果是一组庞大且简单的值,我想以最有效的方式存储并存储特定组合的预先计算的平均值、最大值和最小值。其中一种解决方案是为每个更新创建JS中的唯一函数对象,但我认为这不是一种有效的方法?
主要目标是减少执行此类聚合所需的时间,带宽使用次要。
MongoDB
现在已经具备所需的功能,因此更改了正确答案。关于SO伦理问题,我还有点不确定是否正确。 - flindeberg