Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb按条件对所有匹配对象中的所有数组元素进行计数_Mongodb_Mongodb Query_Aggregation Framework - Fatal编程技术网

Mongodb按条件对所有匹配对象中的所有数组元素进行计数

Mongodb按条件对所有匹配对象中的所有数组元素进行计数,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有一个集合,它是如下对象的活动日志: { "_id" : ObjectId("55e3fd1d7cb5ac9a458b4567"), "object_id" : "1", "activity" : [ { "action" : "test_action", "time" : ISODate("2015-08-31T00:00:00.000Z") }, {

我有一个集合,它是如下对象的活动日志:

{
    "_id" : ObjectId("55e3fd1d7cb5ac9a458b4567"),
    "object_id" : "1",
    "activity" : [ 
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-31T00:00:00.000Z")
        },
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-31T00:00:22.000Z")
        }
    ]
}

{
    "_id" : ObjectId("55e3fd127cb5ac77478b4567"),
    "object_id" : "2",
    "activity" : [ 
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-31T00:00:00.000Z")
        }
    ]
}

{
    "_id" : ObjectId("55e3fd0f7cb5ac9f458b4567"),
    "object_id" : "1",
    "activity" : [ 
        {
            "action" : "test_action",
            "time" : ISODate("2015-08-30T00:00:00.000Z")
        }
    ]
}
如果我执行以下查询:

db.objects.find({
    "createddate": {$gte : ISODate("2015-08-30T00:00:00.000Z")},
    "activity.action" : "test_action"}
    }).count()

它返回包含“test_action”的文档计数(此集中为3个),但我需要获取所有test_操作的计数(此集中为4个)。如何做到这一点?

您可以使用聚合来做到这一点:

db.objects.aggregate([
    {$match: {"createddate": {$gte : ISODate("2015-08-30T00:00:00.000Z")}, {"activity.action" : "test_action"}}},
    {$unwind: "$activity"},
    {$match: {"activity.action" : "test_action"}}},
    {$group: {_id: null, count: {$sum: 1}}}
])
这将产生如下结果:

{
    count: 4
}
要做到这一点,最“有效”的方法是跳过altogther,简单地数数。从本质上说,“过滤器”数组可以获得以下结果:

db.objects.aggregate([
{“$match”:{
“createddate”:{
“$gte”:ISODate(“2015-08-30T00:00:00.000Z”)
},
“activity.action”:“test_action”
}},
{“$组”:{
“_id”:空,
“计数”:{
“$sum”:{
“$size”:{
“$setDifference”:[
{“$map”:{
“输入”:“$activity”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.action”,“test_action”]},
“$$el”,
假的
]
}               
}},
[错误]
]
}
}
}
}}
])
MongoDB的未来版本将有
$filter
,这使得这一点更加简单:

db.objects.aggregate([
{“$match”:{
“createddate”:{
“$gte”:ISODate(“2015-08-30T00:00:00.000Z”)
},
“activity.action”:“test_action”
}},
{“$组”:{
“_id”:空,
“计数”:{
“$sum”:{
“$size”:{
“$filter”:{
“输入”:“$activity”,
“as”:“el”,
“条件”:{
“$eq”:[“$$el.action”,“test_action”]
}
}
}
}
}
}}
])

使用
$unwind
会导致文档反规范化,并有效地为每个数组条目创建一个副本。在可能的情况下,您应该避免这种情况,因为成本往往非常高。通过比较,筛选和计算每个文档的数组条目要快得多。与许多阶段相比,这是一个简单的
$match
$group
管道。

谢谢,它可以工作,但它似乎不使用索引,而且在600k文档数据集上的工作速度非常慢。我有
\u id
createddate
activity.action
的索引。我还应该创建哪些索引?聚合确实使用$match阶段的索引(如果在开始时指定),但正如Blakes Seven所说,展开阶段会导致大量开销。我添加了一个编辑,这应该使它运行得更快一些。是的,在展开之前对其进行过滤是个好主意。工作快得多。非常感谢。非常感谢你。在大型数据集上,必须避免使用“$unwind”。查询就像一个符咒。我的知识现在已经很基本了,我还不知道它是如何工作的:)但找到这个答案将是我今天的家庭作业。)