使用聚合框架传递值
Pass Through Values Using 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" }}}
]
获取元数据需要什么魔法?
如果您只想在输出中匹配 'participants.userid': 12345
"participants"
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
]
}
}
}
在最后一个 $group
语句中,您需要告诉 Mongo 它应该 return 哪些字段。目前,您只需要 _id
和 messages
字段。假设您聚合了 return 三个这样的文档:
{
"_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
的三个布尔值?做一个数组?丢弃数据?连接它们?
在这种情况下,由于所有三个值将始终相同(根据定义),您可以说 "I don't care, just give me any one of them"、"give me the second result"、"give me the first" 或 "give me the last"。前两个不可能,所以我们只剩下 $first
或 $last
:
{$group: {
_id: "$_id",
title: {$first: "$title"},
muted: {$first: "$muted"}
}}
当然,在这种情况下使用哪一个并不重要。
我在 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.userid': 12345
"participants"
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
]
}
}
}
在最后一个 $group
语句中,您需要告诉 Mongo 它应该 return 哪些字段。目前,您只需要 _id
和 messages
字段。假设您聚合了 return 三个这样的文档:
{
"_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
的三个布尔值?做一个数组?丢弃数据?连接它们?
在这种情况下,由于所有三个值将始终相同(根据定义),您可以说 "I don't care, just give me any one of them"、"give me the second result"、"give me the first" 或 "give me the last"。前两个不可能,所以我们只剩下 $first
或 $last
:
{$group: {
_id: "$_id",
title: {$first: "$title"},
muted: {$first: "$muted"}
}}
当然,在这种情况下使用哪一个并不重要。