[英]MongoDB aggregate and match the returned keys
問題是,我正在編寫一些代碼來從數據庫中獲取用戶消息。 數據庫具有send_to , sent_by , 消息密鑰,而我要獲取數據密鑰所遵循的命令是
db.users_messages.aggregate({$group: {_id: {to: "$sent_to", by: "$sent_by"}}})
這將返回所有send_to和sent_by Users_ID的列表。 現在讓我們假設,如果user1已將消息發送給user2 ,並且user2也已回復給user1 ,我希望它僅返回user2的user1 ,而不返回user1的user2 。 而當我稍后再檢查此內容時,則剩下的是分頁功能,因為我在聚合上應用了$ limit 。 希望有人能幫忙!
您要問的不是一件容易的事,我認為真正的解決方案是在文檔中包含更多元數據,特別是要以一致的方式表示對話是“之間的”對話。
我的意思是,無論是誰發送消息或誰接收消息,“鍵”對於對話來說都是唯一的。 考慮這兩個基本文件。
{ "from": 1, "to": 2, "between": [1,2] },
{ "from": 2, "to": 1, "between": [1,2] }
在每種情況下,“從”和“到”是每個“用戶”的唯一標識符,這些標識符將始終以特定方式排序。 “中間”數據總是按相同順序排序,可以在創建代碼時完成,也可以使用$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字段,該過程將僅返回一個文檔,其計數為“兩個”,如下所示:
{ "_id" : [ 1, 2 ], "count" : 2 }
因此,在創建或修改此類數據時,在文檔上維護此類數據確實很有意義。 這樣,分組就變得很簡單,因為已經確定了“唯一鍵”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.