MongoDB:使用多个集合中的数据进行过滤

3
我有一个应用程序,它以事件的形式存储用户及其行为。有两个集合,一个是用户集合,另一个是事件集合。这些文档看起来像这样:
用户

事件

{
    "_id" : ObjectId("593aa71e2f9d5140000bb44e"),
    "name" : "Antonette Ortiz",
    "country" : "France"
}

事件

{
    "_id" : ObjectId("593aaa84c685604066a6a0cf"),
    "name" : "message_sent",
    "timestamp" : ISODate("2016-11-01T04:39:52.667Z"),
    "user" : ObjectId("593aa728d135484002399bac"),
    "attributes" : {
        "str" : "plum",
        "int" : 82
    }
}

现在我想要能够根据用户的属性以及他们触发的事件和特定时间范围来获取用户列表。
一个例子查询可能是这样的:“在过去7天内至少发送了3条消息的所有来自法国的用户”。
我如何使用MongoDB实现这一点,还要考虑性能(例如,如果我有几百万个事件)?仅使用两个集合是否足够?还是必须使用聚合/映射减少?如果是这样,您会建议如何更改模式?

聚合查询可以使用lookup实现,也可以在应用程序层面上实现。MapReduce仅适用于单个集合,因此需要一个临时集合来执行lookup操作,这对于操作查询来说并不是很合适。 - Alex Blex
你能提供一个使用lookup进行聚合的例子吗?在应用程序级别上,你会如何处理它?你是指请求数据然后手动合并吗? - benjiman
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/,如果您遇到任何特定问题,请随时提问。使用应用程序层-是的。使用聚合获取所有匹配的事件用户ID,然后按ID获取用户。 - Alex Blex
1个回答

4

根据MongoDB文档

$lookup阶段在输入文档的字段和“连接”集合文档的字段之间进行相等匹配。

例如,要检索上述标准的数据,其聚合查询如下所示

“所有来自法国且在最近7天内至少发送了3条消息的用户。”

db.Event.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $match: {
            name:'message_sent',
            timestamp:{$gte:ISODate("2016-10-25T04:39:52.667+0000"),$lte:ISODate("2016-11-01T04:39:52.667+0000")}
            }
        },

        // Stage 2
        {
            $group: {
               _id:{user:'$user'},
               counter:{$sum:1}
            }
        },

        // Stage 3
        {
            $lookup: {
                "from" : "User",
                "localField" : "_id.user",
                "foreignField" : "_id",
                "as" : "user"
            }
        },

        // Stage 4
        {
            $match: {
             'user.country':'France' ,
            counter:{$gte:3}
            }
        },

    ]



);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接