使用聚合框架传递值

时间:2015-01-21 17:45:18

标签: mongodb mongodb-query aggregation-framework

我在Mongo中有以下文档架构:

{ 
    "_id": "an id",
    "title": "my title",
    "muted": "true",
    "participants": [{ "userid":12345, "more": "data" }, ... ],
    "messages": [{ "message", "details " } ... { } ]
}

我正试图以这种形式获得一系列对象:

[
    { 
        "_id": "an id", 
        "meta" 
        { 
            "title": "my title",
            "muted": "true",
            "participants": [12345, /* user ids only */ ],
        },
        "messages": [{ "message", "details " } ... { } ]
    }
]

我有聚合工作来生成消息和_id:

[
    { $match:
            {
                'participants.user_id': userId
            }
    },
    { $unwind: "$messages" },
    { $match: { 'messages.sent_at': { '$gte': new Date(date) }}},
    { $group: { _id: "$_id", messages: { $addToSet: "$messages" }}}
]

获取元数据需要什么魔力?

2 个答案:

答案 0 :(得分:2)

如果您想在输出“参与者”中匹配'participants.userid': 12345

db.collection.aggregate(
[    
    { $match:
            {
                'participants.userid': 12345
            }
    },
    { $unwind : "$participants"},    
    { $match:
            {
                'participants.userid': 12345
            }
    },
    { $unwind: "$messages" },    
    { $group: { _id: "$_id" , muted : { $first : '$muted'}, title : { $first : '$title'}, messages: { $addToSet: "$messages" }, participants: { $addToSet: "$participants.userid" }}},
    { $project : { "messages" : "$messages" ,'meta.muted': '$muted', 'meta.title': '$title', 'meta.participants': '$participants'} },
]
).result

如果您想要participants中的所有用户ID,无论它是什么。

db.collection.aggregate(
[
    { $match:
            {
                'participants.userid': 12345
            }
    },
    { $project : { "messages" : 1 ,"muted" : 1 , "title" : 1 , "messages" : 1 , "participants" : 1, "ids" : "$participants.userid"  } },
    { $unwind : "$participants"},    
    { $match:
            {
                'participants.userid': 12345
            }
    },
    { $unwind: "$messages" },    
    { $group: { _id: "$_id" , 
         muted : { $first : '$muted'}, title : { $first : '$title'}, 
         ids : { $first : '$ids'},
         messages: { $addToSet: "$messages" },
         participants: { $addToSet: "$participants.userid" }}},
    { $project : { "messages" : "$messages" ,'meta.muted': '$muted', 'meta.title': '$title', 'meta.participants': '$ids'} },
]
).result

输出:

{
    "0" : {
        "_id" : "an id",
        "messages" : [ 
            {
                "message2" : "details2 "
            }, 
            {
                "message" : "details "
            }
        ],
        "meta" : {
            "muted" : "true",
            "title" : "my title",
            "participants" : [ 
                 12345
            ]
        }
    }
}

答案 1 :(得分:0)

在上一篇$group语句中,您需要告诉Mongo应该返回哪些字段。目前,您要求的所有内容都是_idmessages字段。假设您的聚合返回三个文档:

{ 
  "_id": 1111,
  "title": "my title",
  "muted": "true",
  "participants": [{ "userid":12345, "more": "data" }, ... ],
  "messages": { "message": "Foo" }
},
{ 
  "_id": 1111,
  "title": "my title",
  "muted": "true",
  "participants": [{ "userid":12345, "more": "data" }, ... ],
  "messages": { "message": "Bar" }
},
{ 
  "_id": 1111,
  "title": "my title",
  "muted": "true",
  "participants": [{ "userid":12345, "more": "data" }, ... ],
  "messages": { "message": "Baz" }
}

您已经向Mongo询问了$push运营商所有消息的列表,因此我们已经覆盖了这些消息。对于其他字段,不能执行此操作:

{$group: {
  _id: "$_id", 
  title: 1,
  muted: "$muted"
}}

毕竟,Mongo如何知道如何处理三个"my title"值?或者muted的三个布尔值?做一个数组?丢弃数据?连接它们?

在这种情况下,由于所有三个值总是相同(按照定义),你可以说“我不在乎,只给我任何一个”,“给我第二个结果”,“给我第一个“或”给我最后一个“。前两个是不可能的,因此我们选择了$first$last

{$group: {
  _id: "$_id", 
  title: {$first: "$title"},
  muted: {$first: "$muted"}
}}

当然,在这种情况下使用哪一个并不重要。