【问题标题】:Pass Through Values Using Aggregation Framework使用聚合框架传递值
【发布时间】:2015-03-20 08:21:42
【问题描述】:

我在 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" }}}
]

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

【问题讨论】:

  • 在我的解决方案中,我将 'participants.user_id' 更改为 'participants.userid' 并删除了 $match,因为示例文档没有 sent_at 归档
  • 我用关于参与者的两种可能性更新了答案

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

如果你想在输出“参与者”中匹配'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
            ]
        }
    }
}

【讨论】:

  • 唯一的问题是参与者是数组的数组。我该如何解决这个问题?
  • 我更新了答案,添加了 { $unwind : "$participants"},
【解决方案2】:

在最后的$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" }
}

您已经使用 $push 运算符向 Mongo 询问所有消息的列表,因此我们已经涵盖了这一点。对于其他字段,您不能这样做:

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

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

在这种情况下,由于所有三个值始终相同(根据定义),您可以说“我不在乎,只要给我其中一个”、“给我第二个结果”、“给我是第一个”或“给我最后一个”。前两个是不可能的,所以我们只剩下$first$last

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

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

【讨论】:

    猜你喜欢
    • 2015-10-31
    • 2012-12-27
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    相关资源
    最近更新 更多