平均Mongo中的文档的子文档字段

dev*_*dev 1 mongodb

对于给定的记录ID,如果我在MongoDB中有以下内容,如何获取子文档字段的平均值:

/* 0 */
{
    "item" : "1",
    "samples" : [ 
        {
            "key" : "test-key",
            "value" : "1"
        }, 
        {
            "key" : "test-key2",
            "value" : "2"
        }
    ]
}

/* 1 */
{
    "item" : "1",
    "samples" : [ 
        {
            "key" : "test-key",
            "value" : "3"
        }, 
        {
            "key" : "test-key2",
            "value" : "4"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我想获得给定项目id的key ="test-key"值的平均值(在本例中为1).所以平均值应该是$ avg(1 + 3)= 2

谢谢

Ada*_*son 12

您需要使用聚合框架.

您的查询最终会看起来像这样:

db.stack.aggregate([
  { $unwind : "$samples" },
  { $match : { "samples.key" : "test-key" } },
  { $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
  { $group : { _id : "$new_key", answer : { $avg : "$new_value" } } }
])
Run Code Online (Sandbox Code Playgroud)

编辑:我只是弄清楚为什么我无法让上面的查询工作.在上面发布的数据中,您将值定义为文本值而不是数字.您不能跨文本字段求和.

编辑2:以防您需要执行更新:MongoDB如何更改字段的类型

编辑3:说明:

考虑聚合框架的最佳方式就像装配线.查询本身是一个JSON文档数组,其中每个子文档代表程序集中的不同步骤.

第一步,$unwind用于分离"samples"数组中的每个元素,以便我们可以跨所有元素执行操作.如果只使用该步骤运行查询,您将看到我的意思.长话短说 :

{ name : "bob", 
  children : [ {"name" : mary}, { "name" : "sue" } ] 
} 
Run Code Online (Sandbox Code Playgroud)

成为两个文件:

{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Run Code Online (Sandbox Code Playgroud)

第二步,$match就像SQL中的WHERE子句.它会过滤与您定义的条件不匹配的所有文档.在这种情况下,我们只保留samples.key ="test-key"的文档

第三步,$project重新构建文档.在这种情况下,我将项目从数组中拉出来,以便我可以直接引用它们.使用上面的例子..

{ name : "bob", children : [ { "name" : mary } ] }
Run Code Online (Sandbox Code Playgroud)

变

{ new_name : "bob", new_child_name : mary }
Run Code Online (Sandbox Code Playgroud)

最后,$group是魔术发生的地方._id你将在SQL世界中"分组" 的价值.第二个字段是对我在$project步骤中定义的值进行平均.您可以轻松替换$sum以执行求和,但计数操作通常按以下方式完成:my_count : { $sum : 1 }.

这里要注意的最重要的事情是,正在完成的大部分工作是将数据格式化为执行操作很简单的点.:)