MongoDB聚合管道中的平方根

dst*_*eit 7 root exponent mongodb aggregation-framework

有没有办法在MongoDB聚合管道中获取字段的平方根?我想到这样的事情:

db.collection.aggregate(
  { $group: _id: null, sum: { $sum: "$values" }}, 
  { $project: { answer: { $sqrt: "$sum" }}})
Run Code Online (Sandbox Code Playgroud)

我知道$ sqrt不存在,或任何电源运营商,但有没有办法在聚合管道中实现这一点?我知道可以在map-reduce中使用用户定义的函数来完成,但是在汇总管道中是否可以?

chr*_*dam 1

正如@AnandJayabalan 指出的,$sqrt运算符将随 MongoDB 3.2 版一起发布,语法如下:

\n\n
{ $sqrt: <number> }\n
Run Code Online (Sandbox Code Playgroud)\n\n

在你的例子中,这将是

\n\n
db.collection.aggregate([\n  { $group: { _id: null, total: { $sum: "$values" }}}, \n  { $project: { answer: { $sqrt: "$total" }}}])\n
Run Code Online (Sandbox Code Playgroud)\n\n

在撰写本文时,为了解决此问题,John Page 撰写的关于在聚合框架内计算平方根的链接博客文章使用算术原语通过牛顿法计算平方根。

\n\n

为了用一个例子来解释这个算法是如何工作的,假设你想找到一个正数的平方根N。牛顿方法涉及对一个数字进行有根据的猜测A,该数字在平方后将接近等于N

\n\n

例如,如果N = 121,您可能会猜测A = 10,因为A\xc2\xb2 = 100,这是一个接近的猜测,但您可以做得更好。

\n\n

该方法中使用的方程是牛顿平方根方程

\n\n

在此输入图像描述

\n\n

在哪里

\n\n
    \n
  • N是一个正数,您要求其平方根
  • \n
  • \xe2\x88\x9a是平方根符号
  • \n
  • \xe2\x89\x88意思是“大约等于……”
  • \n
  • A是你有根据的猜测
  • \n
\n\n

如有必要,牛顿法允许您多次重复估计以接近精确数字。以约翰·佩奇为例N = 29,您猜测A = 5,您可以将值输入方程和算法步骤

\n\n

A。从猜测开始A = 5

\n\n

b. N 除以猜测值(29/5 = 5.9)

\n\n

C。将其添加到猜测中(5.9 + 5 = 10.9)

\n\n

d. 然后将该结果除以 2(10.9/2 = 5.45)

\n\n

e. 将其设置为新的猜测A = 5.45,并从 b 开始重复

\n\n
\n

5.45\n 5.38555\n 5.38516

\n
\n\n

经过 2 次迭代后,答案为3.1623,它接近平方根的精确值。

\n\n

现在,使用聚合框架(来自 John Page 的博客文章)并将其应用到您的示例中,聚合管道将是:

\n\n
var groupPipeline = { $group: _id: null, total: { $sum: "$values" } },\n    firstGuess = { \n        $project : { \n            n : "$total", r : { $literal : 5 } /* similar to step a) in the algorithm, the $literal operator sets r to the value 5 */\n        } \n    },\n    refineStep = { \n        $project : { \n            n: 1, r : { \n                $divide : [  /* step d) of the algorithm */\n                    { \n                        $add : [ /* step c) of the algorithm */\n                            { $divide : [ "$n", "$r"] },  /* step b) of the algorithm */\n                            "$r" \n                        ]\n                    },\n                    2 \n                ]\n            }\n        }\n    };\n\n/* Run the aggregation pipeline */\n> db.collection.aggregate(groupPipeline, firstGuess, refineStep, refineStep, refineStep)\n\n> { "_id" : ObjectId("538062103439ddd3764ff791"), "n" : 29, "r" : 5.385164807134505 }\n
Run Code Online (Sandbox Code Playgroud)\n