对于给定的记录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"
}
]
}
我想获得给定项目id的key =“test-key”值的平均值(在本例中为1)。所以平均值应该是$ avg(1 + 3)= 2
由于
答案 0 :(得分:11)
您的查询最终会看起来像这样:
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" } } }
])
编辑:我只是弄清楚为什么我无法让上面的查询工作。在上面发布的数据中,您将值定义为文本值而不是数字。您不能跨文本字段求和。
编辑2:以防您需要执行更新:MongoDB How to change the type of a field
编辑3:说明:
考虑聚合框架的最佳方式就像装配线。查询本身是一个JSON文档数组,其中每个子文档代表程序集中的不同步骤。
第一步$unwind
用于分隔“samples”数组中的每个元素,以便我们可以跨所有元素执行操作。如果只使用该步骤运行查询,您将看到我的意思。
长话短说:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
成为两个文件:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
第二步$match
就像SQL中的WHERE子句。它会过滤与您定义的条件不匹配的所有文档。在这种情况下,我们只保留samples.key =“test-key”
第三步$project
重新构建文档。在这种情况下,我将项目从数组中拉出来,以便我可以直接引用它们。使用上面的例子..
{ name : "bob", children : [ { "name" : mary } ] }
变为
{ new_name : "bob", new_child_name : mary }
最后,$group
是神奇发生的地方。 _id
值将在SQL世界中“分组”。第二个字段是对我在$project
步骤中定义的值进行平均。您可以轻松替换$sum
来执行求和,但计数操作通常通过以下方式完成:my_count : { $sum : 1 }
。
这里需要注意的最重要的事情是,要完成的大部分工作是将数据格式化到执行操作很简单的程度。 :)