假设您有大量的用户(M)和大量文档(n),并且您希望每个用户能够将每个文档标记为读取或未读取(就像任何电子邮件系统一样)。在MongoDB中代表这一点的最佳方法是什么?还是任何其他文档数据库?

在Stackoverflow上有几个问题,询问此问题有关关系数据库的问题,但我没有看到有关文档数据库的建议:

记住多个项目的阅读/未阅读状态的最有效方法是什么?

实施“未读评论”计数器的有效系统

通常,答案涉及一个表列出用户读取的所有内容的表:(即用户ID的元组,文档ID)具有一些可能的优化,以进行截止日期,以允许Mark-All-As-Read读取数据库,然后再次开始知道任何内容在此日期之前是“读取”。

因此,MongoDB / NOSQL专家,您在实践中看到了哪些方法,这些方法是如何执行的?

有帮助吗?

解决方案

{
_id: messagePrefs_uniqueId,
type: 'prefs',
timestamp: unix_timestamp
ownerId: receipientId,
messageId: messageId,
read: true / false,
}

{
_id: message_uniqueId,
timestamp: unix_timestamp
type: 'message',
contents: 'this is the message',
senderId: senderId,
recipients: [receipientId1,receipientId2]
}

假设您有3条要检索首选项的消息,您可以通过类似的内容获取它们:

db.messages.find({
messageId : { $in : [messageId1,messageId2,messageId3]},
ownerId: receipientId, 
type:'prefs'
})

如果您需要阅读/未阅读,则可以使用MongoDB的UPSERT功能来使用此信息,因此除非用户实际读取它,否则您不会为每个消息创建PERFS,然后基本上您可以使用自己的唯一ID创建PERFS对象,然后将其UPSERT upsert upsert to MongoDB中。如果您想要更大的灵活性(例如标签或文件夹),则可能需要为消息的每个接收者制作PERF。例如,您可以添加:

tags: ['inbox','tech stuff']

到prefs对象,然后获取所有带有“技术内容”标记的消息的prefs,您会喜欢以下内容:

db.messages.find({type: 'prefs', ownerId: recipientId, tags: 'tech stuff'})

然后,您可以使用您在prefs中找到的邮件ID来查询并查找所有相应的消息:

db.messages.find((type:'message', _id: { $in : [array of messageIds from prefs]}})

如果您想做一些诸如计算每个“标签”有效包含多少消息之类的事情,那可能会有些棘手。如果只有几个标签,您只需添加 .count() 到每个查询的查询末尾。如果是数百或数千个,那么您可能会使用地图/减少服务器端脚本或可能跟踪每个用户每个标签的消息计数的对象做得更好。

其他提示

如果您仅存储一个简单的布尔值,例如读/未读取,另一种方法是嵌入每个文档中包含读取它的用户列表的数组。

{
  _id: 'document#42',
  ...
  read_by: ['user#83', 'user#2702']
}

然后,您应该能够为该字段索引,从而为文档阅读用户和用户读取文档提供快速查询。

db.documents.find({read_by: 'user#83'})

db.documents.find({_id: 'document#42}, {read_by: 1})

但是,我发现我通常会查询所有具有的文档 不是 是由特定用户阅读的,在这种情况下,我无法想到可以利用索引的任何解决方案。我怀疑不可能在没有两者的情况下做到这一点 read_byunread_by 数组,使每个用户都包含在每个文档(或加入表)中,但这将具有较大的存储成本。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top