Mongodb找到不同的数组字段并计算它们

时间:2015-09-30 14:10:13

标签: mongodb aggregation-framework

我的收藏文件看起来像:

{
    "_id" : ObjectId("560ba1e86db58e34168b456a"),
    "object_id" : "1722224",
    "user" : {
        "id" : null,
        "cookie" : "sEnAl9DdPHyTdmxYU3E23g"
    },
    "createddate" : ISODate("2015-09-30T11:48:40.000+03:00"),
    "activity" : [ 
        {
            "name" : "Map click",
            "selector" : "#toMap",
            "event" : "click",
            "time" : ISODate("2015-09-30T12:30:59.000+03:00")
        },
        {
            "name" : "Show contacts (main block)",
            "selector" : "#jsn-showContacts",
            "event" : "click",
            "time" : ISODate("2015-09-30T11:48:47.687+03:00")
        },
        {
            "name" : "Show contacts (main block)",
            "selector" : "#jsn-showContacts",
            "event" : "click",
            "time" : ISODate("2015-09-30T15:34:12.000+03:00")
        }
    ]
}

我需要传递到mongodb日期范围并获得包含以下内容的日常结果:  1.日期  2.选择器集点击了该点击的日期和计数:

{
    "date" :  ISODate("2015-09-29T00:00:00.000+03:00"),
    "selectors" : [
        {"#toMap" : 100},
        {"#jsn-showContacts" : 200}
    ]
},   
{
    "date" :  ISODate("2015-09-30T00:00:00.000+03:00"),
    "selectors" : [
        {"#toMap" : 50},
        {"#jsn-showContacts" : 80},
        {"#toOrder" : 10}
    ]
}

对于每个文档,结果应该计算一次,例如,如果我在一个文档中有两次#showContacts-Min次点击:

"activity" : [ 
            {
                "name" : "Show contacts (main block)",
                "selector" : "#jsn-showContacts",
                "event" : "click",
                "time" : ISODate("2015-09-30T11:48:47.687+03:00")
            },
            {
                "name" : "Show contacts (main block)",
                "selector" : "#jsn-showContacts",
                "event" : "click",
                "time" : ISODate("2015-09-30T15:34:12.000+03:00")
            }
        ]

必须保持一次。

是否真的可以在数据库端进行一次查询,还是应该在具有多个数据库查询的应用程序端实现?

1 个答案:

答案 0 :(得分:2)

很有可能使用单个查询获得所需的结果。我假设您的“选择器”值是事先知道的,以便它可以在MongoDB查询中进行硬编码。

在这里,我根据您的架构创建了示例文档:

> db.a.find().pretty()
{
    "_id" : ObjectId("560ba1e86db58e34168b456a"),
    "object_id" : "1722224",
    "user" : {
            "id" : null,
            "cookie" : "sEnAl9DdPHyTdmxYU3E23g"
    },
    "createddate" : ISODate("2015-09-30T08:48:40Z"),
    "activity" : [
            {
                    "name" : "Map click",
                    "selector" : "#toMap",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T09:30:59Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T08:48:47.687Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T12:34:12Z")
            }
    ]
}
{
    "_id" : ObjectId("560c19550e45be0a683ccd01"),
    "object_id" : "1722224",
    "user" : {
            "id" : null,
            "cookie" : "sEnAl9DdPHyTdmxYU3E23g"
    },
    "createddate" : ISODate("2015-10-30T08:48:40Z"),
    "activity" : [
            {
                    "name" : "Map click",
                    "selector" : "#toMap",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T09:30:59Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T08:48:47.687Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T12:34:12Z")
            }
    ]
}
{
    "_id" : ObjectId("560c19750e45be0a683ccd02"),
    "object_id" : "1722224",
    "user" : {
            "id" : null,
            "cookie" : "sEnAl9DdPHyTdmxYU3E23g"
    },
    "createddate" : ISODate("2015-10-30T08:48:40Z"),
    "activity" : [
            {
                    "name" : "Map click",
                    "selector" : "#toMap",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T09:30:59Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T08:48:47.687Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T12:34:12Z")
            }
    ]
}
{
    "_id" : ObjectId("560c19940e45be0a683ccd03"),
    "object_id" : "1722224",
    "user" : {
            "id" : null,
            "cookie" : "sEnAl9DdPHyTdmxYU3E23g"
    },
    "createddate" : ISODate("2016-01-30T08:48:40Z"),
    "activity" : [
            {
                    "name" : "Map click",
                    "selector" : "#toMap",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T09:30:59Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T08:48:47.687Z")
            },
            {
                    "name" : "Show contacts (main block)",
                    "selector" : "#jsn-showContacts",
                    "event" : "click",
                    "time" : ISODate("2015-09-30T12:34:12Z")
            }
    ]
}

下面的查询将给出您的结果。选择此计数而不考虑单个文档中的重复值

   >db.a.aggregate([{"$match":
{createddate:{"$gt": ISODate("2014-10-30T11:48:40.000+03:00"),
         "$lt":ISODate("2016-10-30T11:48:40.000+03:00")}}},
{'$group':{"_id":{"date":"$createddate"},
       "#toMap":{"$sum":{"$cond":{"if":{"$anyElementTrue":{
                                      "$map":{"input":"$activity",
                                               "as":"act",
                                               "in":{"$eq":    ["$$act.selector","#toMap"]}}}},"then":1,"else":0}}},
        "#jsn-showContacts":{"$sum":{"$cond":{"if":{"$anyElementTrue":{
                                        "$map":{
                                        "input":"$activity",
                                        "as":"act",
                                        "in":{"$eq":["$$act.selector","#jsn-    showContacts"]}}}},"then":1,"else":0}}}}}])
//Result:
{ "_id" : { "date" : ISODate("2016-01-30T08:48:40Z") }, "#toMap" : 1, "#jsn-showContacts" : 1 }
{ "_id" : { "date" : ISODate("2015-10-30T08:48:40Z") }, "#toMap" : 2, "#jsn-showContacts" : 2 }
{ "_id" : { "date" : ISODate("2015-09-30T08:48:40Z") }, "#toMap" : 1, "#jsn-showContacts" : 1 }

选择器不在Result中的数组中,但我希望这样做。您可以使用$ project作为最后的pipelie阶段来修改结果模式