2011-12-07 58 views
2

型號MongoDB的查詢/建模thougths

我有聊天室的集合:

ObjectId Id 
ObjectId GroupId 
ObjectId LastMessageId 
List<ObjectId> Members 
bool IsEveryone 

我有ChatMessage的集合:

ObjectId GroupId 
ObjectId RoomId 
ObjectId Id 
ObjectId UserId 
string Text 
DateTime Date 

背景

每個用戶都是多個組的一部分。每個組包含多個房間。我擁有用戶所屬的所有房間以及迄今爲止用戶看到的最後一條消息ID的數組。

這個想法是計算給定用戶的增量:(1)從所有房間取回所有最後的消息ID並(2)計算用戶錯過了多少聊天消息(新消息)。

服務器獲取用戶目前看到的最新的msg id(因此我可以獲取該消息的日期並計算該用戶沒有看到多少個新消息)。

查詢

什麼我要找的是運行2個快速查詢一種方式:

  1. 返回每間客房最新的消息ID(按日期,DESC)。 輸入:房間號碼數組。 輸出:數組[室-ID]:[MSG-ID]

  2. 計算的新郵件(整數)如何每房間存在給定用戶的輸入:[user-id,room-id,last-message-date]的數組。 輸出:[room-id]的數組:[int]。請注意,我不想計算用戶編寫的消息。

你可以幫助構建優化查詢嗎?我正在使用MongoDB C#10gen SDK。

UPDATE:

每次我現在寫一個新的聊天消息,我也跑在聊天室,以保持LastMessageId原子更新。這可以在保持性能的同時解決第一個查詢(讀取速率>寫入速率)。

+1

你說的是房間+小組,但是在你的預期輸出中你只提到房間ID。你能更好地解釋這兩者之間的關係嗎?此外,還不清楚您是否希望針對特定情況(例如單個房間/組ID)的答案或針對所有情況(例如地圖減少查詢)的答案的聚合結果。嘗試澄清您的預期輸入和輸出。 – Avish

+1

阿維什 - 集團有多個房間。我已將預期結果更新爲:groupId,roomId,lastMsgId。我會更新所需的輸入/輸出,所以事情會很清楚。 –

回答

2

要回答你的問題:

1。爲了達到最佳的性能,你需要創建適當的複合索引:

db.ChatMessage.ensureIndex({GroupId: 1, RoomId:1, Date: -1}) 

然後查詢將是這樣的:

db.ChatMessage.find({GroupId: 2, RoomId:3}).sort({"Date": -1}) 

如果您需要只返回{RoomId, MessageId}對象,你可以指定這些字段:

db.ChatMessage.find({GroupId: 2, RoomId:3}, //filter messages 
      {RoomId:1, _id:1}) // specify set of fields thats query should return 
      .sort({"Date": -1}) // sort by date desc 
      .limit(10) // take a specific number of last messagies 

要確保查詢使用正確的索引,您可以使用explain()方法。

2.關於第二個問題,我建議prerecalculate的使用set運營商而不是使用的map/reduce新messagies數字,因爲它工作的大數據集的緩慢。或者另一個不錯的選擇可以是異步映射/減少incremental

根據您在房間集合中的需求,您可以有NumberOfNewMessagies或嵌套數組[{UserId, MessagiesCount}]。所以,當你加載空間時,你總會有一些新的消息。

順便說一句,讓我知道如果你有任何麻煩將mongodb shell查詢轉換成C#代碼。

希望這對你有幫助。

+0

安德魯 - 感謝您的快速回復!我在問題中增加了一些更多細節,希望更清楚。注意需要的輸入/輸出。我很想知道你認爲我應該如何處理它。 –