有没有办法在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是一个很接近的猜测,但是您可以做得更好。

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

mongodb - MongoDB聚合管道中的平方根-LMLPHP

在哪里
  • 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/

    10-12 18:11