型号
我有一个 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(因此我可以提取该消息的日期并计算存在多少用户未看到的新消息)。
查询
我正在寻找的是一种运行 2 个快速查询的方法:
返回每个房间的最新消息 ID(按日期,desc)。 输入:房间id数组。 输出:[room-id]:[msg-id]的数组
计算给定用户的每个房间存在多少条新消息(整数)。 输入:[user-id, room-id, last-message-date] 数组。 输出:[room-id]:[int] 数组。请注意,我不想对用户写的消息进行计数。
您能帮助构建优化查询吗?我正在使用 MongoDB C# 10gen SDK。
更新:
每次我现在写一条新的聊天消息时,我还会在 ChatRoom 上运行一个原子更新以保留 LastMessageId。这解决了第一个查询,同时保持性能健全(读取速率 > 写入速率)。
最佳答案
将回答您的问题。:
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# 代码时遇到任何问题,请告诉我。
希望对您有所帮助。
关于c# - MongoDB 查询/建模思想,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8420821/