MongoDB查询/建模

本文关键字:建模 查询 MongoDB | 更新日期: 2023-09-27 18:17:09

Model

我有一个聊天室的集合:

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

我有一个聊天消息的集合:

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

背景

每个用户都是多个组的一部分。每组包含多个房间。我拥有用户所属的所有房间以及用户到目前为止看到的最后消息 id 的数组。

这个想法是计算给定用户的增量:(1( 从所有房间带回所有最后的消息 ID,以及 (2( 计算用户错过的聊天消息数量(新消息(。

服务器获取用户到目前为止看到的最新消息 ID(因此我可以提取该消息的日期并计算存在多少用户未看到的新消息(。

查询

我正在寻找一种运行 2 个快速查询的方法:

  1. 返回每个房间的最新消息 ID(按日期,说明(。输入:房间 ID 数组。输出:[房间 ID] 的数组:[消息 ID]

  2. 计算给定用户每个房间存在多少条新消息(整数(。输入:[用户 ID、房间 ID、最后消息日期] 数组。输出:[房间 ID]:[int] 的数组。请注意,我不想计算用户编写的消息。

你能帮助构建优化的查询吗?我正在使用MongoDB C# 10gen SDK。

更新:

每次我写一条新的聊天消息时,我也会在聊天室上运行原子更新以保留 LastMessageId。这将解决第一个查询,同时保持性能正常(读取速率>写入速率(。

MongoDB查询/建模

将回答您的问题:

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. 对于您的第二个问题,我建议使用集合运算符预先重新计算新消息的数量,而不是使用 map/reduce,因为它对于大数据集的工作速度很慢。或者另一个不错的选择可以是增量异步映射/减少。

根据您的需求,在房间集合中,您可以有NumberOfNewMessagies,或嵌套数组[{UserId, MessagiesCount}]。因此,当您装入空间时,您将始终拥有许多新消息。

顺便说一句,如果您遇到将MongoDB shell查询转换为C#代码时遇到任何问题,请告诉我。

希望这对您有所帮助。