有没有办法在MongoDB聚合管道中获得字段的平方根?我想到这样的事情:
db.collection.aggregate(
{ $group: _id: null, sum: { $sum: "$values" }},
{ $project: { answer: { $sqrt: "$sum" }}})
我知道$ sqrt不存在,或者没有任何运算符,但是有没有办法在聚合管道中完成此操作?我知道可以通过map-reduce中的用户定义函数来完成,但是在聚合管道中是否有可能?
最佳答案
正如@AnandJayabalan指出的那样, $sqrt
运算符将与MongoDB 3.2版一起发布,其语法为:
{ $sqrt: <number> }
在您的示例中,这将是
db.collection.aggregate([
{ $group: { _id: null, total: { $sum: "$values" }}},
{ $project: { answer: { $sqrt: "$total" }}}])
在撰写本文时,为了解决此问题,John Page所链接的有关calculating square roots within the aggregation framework的博客文章使用算术基元来通过Newton's method计算平方根。
仅为了说明该算法的工作原理,假设您要查找正数
N
的平方根。牛顿的方法涉及对数字A
进行有根据的猜测,该数字在平方时将接近等于N
。例如,如果使用
N = 121
,您可能会猜测A = 10
,因为A² = 100
是一个很接近的猜测,但是您可以做得更好。此方法中使用的方程是牛顿平方根方程:
在哪里
N
是要查找其平方根的正数√
是平方根符号≈
的意思是“大约等于...” A
是您的有根据的猜测牛顿法可以让您重复估算多次,以逼近一个确切的数。以约翰·佩奇(John Page)的
N = 29
为例,您可以猜测A = 5
,您可以将值输入方程式和算法步骤中从猜测
A = 5
开始b。 将N除以猜测
(29/5 = 5.9)
c。 将其添加到猜测
(5.9 + 5 = 10.9)
中d。 然后将结果除以2
(10.9/2 = 5.45)
e。 将其设置为新的猜测
A = 5.45
,并从 b开始重复。 经过2次迭代,答案是
3.1623
,它接近平方根的确切值。现在,使用聚合框架(来自John Page的博客文章)并将其应用于您的示例,聚合管道将为:
var groupPipeline = { $group: _id: null, total: { $sum: "$values" } },
firstGuess = {
$project : {
n : "$total", r : { $literal : 5 } /* similar to step a) in the algorithm, the $literal operator sets r to the value 5 */
}
},
refineStep = {
$project : {
n: 1, r : {
$divide : [ /* step d) of the algorithm */
{
$add : [ /* step c) of the algorithm */
{ $divide : [ "$n", "$r"] }, /* step b) of the algorithm */
"$r"
]
},
2
]
}
}
};
/* Run the aggregation pipeline */
> db.collection.aggregate(groupPipeline, firstGuess, refineStep, refineStep, refineStep)
> { "_id" : ObjectId("538062103439ddd3764ff791"), "n" : 29, "r" : 5.385164807134505 }
关于mongodb - MongoDB聚合管道中的平方根,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25393817/