假设我在MongoDB中有1,000,000,000个实体,每个实体都有3个数字属性,A,B和C.
例如:
entity1 : { A: 35, B: 60, C: 5 }
entity2 : { A: 15, B: 10, C: 55 }
entity2 : { A: 10, B: 10, C: 10 }
...
现在我需要查询数据库。查询的输入将是3个数字:(a, b, c)
。结果将是按加权平均值定义的降序实体列表,或A * a + B * b + C * c
。
所以q(1, 100, 1)
会返回(entity1, entity2, entity3)
并q(1, 1, 100)
将返回(entity2, entity1, entity3)
使用MongoDB可以实现这样的事情,而无需计算每个查询中每个实体的加权平均值吗?我没有绑定MongoDB,但我正在学习MEAN堆栈。如果我必须使用其他东西,那也没关系。
注意:我选择了1,000,000,000个实体作为极端的例子。我的实际用例只有~5000个实体,所以迭代一切可能没问题,我只是对一个更聪明的解决方案感兴趣。
答案 0 :(得分:1)
当然,如果你提供输入并且不能使用预先计算的字段,你必须计算它,但这里唯一的区别是返回所有项目并在客户端中对它们进行排序或让服务器完成工作: / p>
var a = 1,
b = 1,
c = 100;
db.collection.aggregate(
[
{ "$project": {
"A": 1,
"B": 1,
"C": 1,
"weight": {
"$add": [
{ "$multiply": [ "$A", a ] },
{ "$multiply": [ "$B", b ] },
{ "$multiply": [ "$C", c ] }
]
}
}},
{ "$sort": { "weight": -1 } }
],
{ "allowDiskUse": true }
)
因此,此处的关键是.aggregate()
方法允许生成应用$sort
的值所需的文档操作。
在此之前的$project
管道阶段中,使用$multiply
对每个输入到管道的外部变量的字段值提供计算值,最后的数学运算执行$add
在结果中的每个参数上产生" weight"作为一个排序的领域。
您不能直接将算法提供给任何"排序" MongoDB中的方法,因为它们需要对文档中存在的字段起作用。聚合框架为"项目提供了手段。这个值,因此后来的管道阶段可以执行所需的排序。
另一种情况是,由于您通常建议的文档大小,最好提供"allowDiskUse"作为选项,强制聚合过程将处理过的文档临时存储在磁盘而不是内存中,因为有restriction on the amount of memory可以在没有此选项的聚合过程中使用。