问题是,我正在编写一些代码来从我的数据库中获取用户消息。数据库有 sent_to , sent_by ,消息键以及我正在关注以获取数据密钥的命令
db.users_messages.aggregate({$group: {_id: {to: "$sent_to", by: "$sent_by"}}})
这将返回所有 sent_to 和 sent_by Users_IDs的列表。现在让我们假设 user1 已将消息发送到 user2 并且 user2 已回复 user1 ,我想要它仅为 user2 返回 user1 ,而不为 user1 返回 user2 。而当我稍后检查这个东西时,我就会留下分页的东西,因为我在聚合上应用了 $ limit 。 希望有人可以帮忙!
答案 0 :(得分:1)
你所要求的是一个不小的壮举,我认为这里的真正解决方案是在你的文件中加入更多的元数据,特别是以一致的方式表示对话是谁“之间”。
我的意思是,无论是谁发送消息或谁接收,“密钥”都必须是对话的独特之处。考虑这两个基本文件。
{ "from": 1, "to": 2, "between": [1,2] },
{ "from": 2, "to": 1, "between": [1,2] }
在每种情况下,“from”和“to”是每个“用户”的唯一标识符,它们将始终以特定方式排序。 “between”数据总是按照相同的顺序排序,这可以在您创建的代码中完成,也可以通过$sort
修饰符和$each
的“upsert”功能完成,但重点是保留用于确定哪些文档属于同一分组的“唯一”密钥。
单独使用聚合框架是可能的,但是如果您认为可以在文档中保留它,那么它实际上是不必要的箍跳:
db.converse.aggregate([
{ "$group": {
"_id": "$_id",
"from": { "$push": "$from" },
"to": { "$push": "$to" }
}},
{ "$project": {
"between": { "$setUnion": [ "$from", "$to" ] }
}},
{ "$unwind": "$between" },
{ "$sort": { "between": 1 } },
{ "$group": {
"_id": "$_id",
"between": { "$push": "$between" }
}},
{ "$group": {
"_id": "$between",
"count": { "$sum": 1 }
}}
])
在早于MongoDB 2.6的版本中,没有类似**$setUnion
的版本,可以用不同的方式组合成一个数组:
db.converse.aggregate([
{ "$project": {
"from": 1,
"to": 1,
"type": { "$const": [ "from", "to" ] },
}},
{ "$unwind": "$type" },
{ "$group": {
"_id": "$_id",
"between": {
"$addToSet": {
"$cond": [
{ "$eq": [ "$type", "from" ] },
"$from",
"$to"
]
}
}
}},
{ "$unwind": "$between" },
{ "$sort": { "between": 1 } },
{ "$group": {
"_id": "$_id",
"between": { "$push": "$between" }
}},
{ "$group": {
"_id": "$between",
"count": { "$sum": 1 }
}}
])
在每种情况下,都有合理数量的偏执表现为“不订购套装”。它们可能恰好以这种方式出现,但你可能不能指望它。
这里的原理基本相同,在“between”元素中创建一个唯一排序的“列表”,然后将其用作分组键。从上面的示例文档中,忽略现有的between字段,进程将只返回一个计数为“two”的文档,如下所示:
{ "_id" : [ 1, 2 ], "count" : 2 }
因此,在创建或修改文档时,在文档上维护此类数据确实很有意义。以这种方式,分组变得简单,因为已经识别出“唯一密钥”