2015-01-13 152 views
1

有消息的集合:MongoDB中獲得最後的組合,聚合框架

{ 
    "date": NumberLong(1421134514), 
    "sender": "53172480f9cd0e682840b9f7", 
    "recipient": "52f37fbaf9cd0e02773c97b1", 
    "isRead": false, 
    "_id": "54b4cab2f6a48ce34f8b5a75", 
    "text": "Hello!" 
}, 
{ 
    "date": NumberLong(1421135561), 
    "sender": "53172480f9cd0e682840b9f7", 
    "recipient": "52f37fbaf9cd0e02773c97b1", 
    "isRead": false, 
    "_id": "54b4cec9f6a48ce34f8b6429", 
    "text": "Hello 2!" 
}, 
{ 
    "date": NumberLong(1421135618), 
    "sender": "53072122f9cd0ee76306dc5a", 
    "recipient": "52f37fbaf9cd0e02773c97b1", 
    "isRead": false, 
    "_id": "54b4cf02f6a48ce54f8b62f9", 
    "text": "Hello 3!" 
}, 
{ 
    "date": NumberLong(1421136457), 
    "sender": "52f37fbaf9cd0e02773c97b1", 
    "recipient": "52ea178ff9cd0e9f24d776b4", 
    "isRead": false, 
    "_id": "54b4d249f6a48ce54f8b6b9f" 
    "text": "Hello 4!" 
} 

有必要選擇後者對話,在當前用戶是發送者或接收者。

例如,對於ID ='52f37fbaf9cd0e02773c97b1'的用戶,應該獲得3條記錄。

事實證明,建立兩個單獨的查詢:

$result = \DB::$connection->message->aggregate(array(
    array('$match' => array('sender' => \Core::getModule('users')->user->_id)), 
    array('$group' => array('_id' => '$recipient')), 
)); 

$result2 = \DB::$connection->message->aggregate(array(
    array('$match' => array('recipient' => \Core::getModule('users')->user->_id)), 
    array('$group' => array('_id' => '$sender')), 
)); 

是否有可能這兩個查詢以某種方式合併成一個,並按日期排序記錄?

+0

不清楚你在問什麼。這兩個聚合查詢將只返回一個具有單一「_id」值的元素。你想做什麼? –

+0

選擇帶有唯一對話者的此人的最新帖子 – jeka5555

+0

我需要顯示參與用戶的對話列表,並按日期最後一則消息對其進行排序。 – jeka5555

回答

2

您需要的是爲每個「發件人和收件人」組合生成的「唯一密鑰」值。如果你想定期這樣做,那麼我會建議將值存儲在文檔中。但是,這是一種方式,你可以使用聚合框架讓出了問題:

db.messages.aggregate([ 
    { "$project": { 
     "combined": { "$map": { 
      "input": { "$literal": ["A","B"] }, 
      "as": "bin", 
      "in": { "$cond": [ 
       { "$eq": [ "$$bin", "A" ] }, 
       "$sender", 
       "$recipient" 
      ]} 
     }}, 
     "doc": "$$ROOT" 
    }}, 
    { "$unwind": "$combined" }, 
    { "$sort": { "_id": 1, "combined": 1, "doc.date": -1 } }, 
    { "$group": { 
     "_id": "$_id", 
     "combined": { "$push": "$combined" }, 
     "doc": { "$first": "$doc" } 
    }}, 
    { "$group": { 
     "_id": "$combined", 
     "doc": { "$first": "$doc" } 
    }} 
]) 

那你的樣本範圍縮小到「發件人/接受者」「獨一無二」的3個組合並返回最後文件中的談話之間「對」:

{ 
    "_id" : [ 
      "52f37fbaf9cd0e02773c97b1", 
      "53172480f9cd0e682840b9f7" 
    ], 
    "doc" : { 
      "_id" : "54b4cec9f6a48ce34f8b6429", 
      "date" : NumberLong(1421135561), 
      "sender" : "53172480f9cd0e682840b9f7", 
      "recipient" : "52f37fbaf9cd0e02773c97b1", 
      "isRead" : false, 
      "text" : "Hello 2!" 
    } 
} 
{ 
    "_id" : [ 
      "52f37fbaf9cd0e02773c97b1", 
      "53072122f9cd0ee76306dc5a" 
    ], 
    "doc" : { 
      "_id" : "54b4cf02f6a48ce54f8b62f9", 
      "date" : NumberLong(1421135618), 
      "sender" : "53072122f9cd0ee76306dc5a", 
      "recipient" : "52f37fbaf9cd0e02773c97b1", 
      "isRead" : false, 
      "text" : "Hello 3!" 
    } 
} 
{ 
    "_id" : [ 
      "52ea178ff9cd0e9f24d776b4", 
      "52f37fbaf9cd0e02773c97b1" 
    ], 
    "doc" : { 
      "_id" : "54b4d249f6a48ce54f8b6b9f", 
      "date" : NumberLong(1421136457), 
      "sender" : "52f37fbaf9cd0e02773c97b1", 
      "recipient" : "52ea178ff9cd0e9f24d776b4", 
      "isRead" : false, 
      "text" : "Hello 4!" 
    } 
} 
+0

_這裏你需要的是爲每個「發件人和收件人」組合生成的「唯一密鑰」值。如果你想定期做這個,那麼我會建議將這個值存儲在文檔中。我想到了它,但最終恐怕要延長每個文檔16 MB的限制。 – jeka5555

+0

@ jeka5555這裏的16MB限制實際上是關於在'[「發件人」,「收件人」]'之間存儲組合數組的組合,以及發送者和可能的「多個「收件人。數組中有很多對。這不是我真正回答的問題(但也不難解決)。我的示例顯示了您可以「當前」執行的「聚合分組」(不更改模式或存儲),然後獲得您要求的內容。我希望俄文翻譯能夠在這些內容上運行得很好。 –

+1

@ jeka5555在這裏可以明確我沒有爲「發件人/收件人」呈現兩個「ObjectId」值的「或」組合。我正在展示**所有可能的配對**。但是你總是可以縮小這個範圍。 –