模型
我有一个ChatRoom的集合:
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)计算用户错过的聊天消息数量(新消息) )。
服务器获取用户到目前为止看到的最新消息ID(因此我可以提取消息的日期并计算用户未看到的新消息的数量)。< / p>
查询
我正在寻找的是一种运行2个快速查询的方法:
返回每个房间的最新消息ID(按日期,desc)。 输入:room-id数组。 输出:[room-id]数组:[msg-id]
计算给定用户每个会议室有多少新消息(整数)。 输入:[user-id,room-id,last-message-date]的数组。 输出:[room-id]数组:[int]。请注意,我不想计算用户写的消息。
您可以帮助构建优化查询吗?我正在使用MongoDB C#10gen SDK。
更新
每次我现在写一条新的聊天消息时,我还会在ChatRoom上运行原子更新以保留LastMessageId。这解决了第一个查询,同时保持了完整性(读取速率&gt;写入速率)。
答案 0 :(得分: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。对于您的第二个问题,我建议使用set运算符预先计算新信息的数量,而不是使用map / reduce,因为它对大数据集的工作速度很慢。或者另一个好的选择可以是incremental异步map / reduce。
根据您在房间集合中的需求,您可以拥有NumberOfNewMessagies
或嵌套数组[{UserId, MessagiesCount}]
。因此,当你装载房间时,你总会有许多新的信息。
顺便说一句,如果你有麻烦将mongodb shell查询转换为c#代码,请告诉我。
希望这对你有所帮助。