假设您有大量用户 (M) 和大量文档 (N),并且您希望每个用户能够将每个文档标记为已读或未读(就像任何电子邮件系统一样)。在 MongoDB 中表示这一点的最佳方式是什么?还是其他任何文档数据库?
StackOverflow 上有几个问题针对关系数据库提出了这个问题,但我没有看到任何有关文档数据库的建议:
What's the most efficient way to remember read/unread status across multiple items?
Implementing an efficient system of "unread comments" counters
通常,答案涉及一个表格,其中列出了用户已阅读的所有内容:(即用户 ID 的元组、文档 ID)以及一些可能的截止日期优化,允许标记为已读以删除数据库并重新开始知道该日期之前的任何内容都是“已读”。
那么,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 功能一起使用,因此您不会为每条消息创建首选项,除非用户实际阅读它,然后基本上您使用自己的唯一 id 和 upsert 创建首选项对象它进入MongoDB。如果您想要更多的灵 active (例如标签或文件夹),您可能希望为每个邮件收件人设置首选项。例如,您可以添加:
tags: ['inbox','tech stuff']
到 prefs 对象,然后获取所有标记为“tech stuff”的消息的所有 prefs,你可以这样做:
db.messages.find({type: 'prefs', ownerId: recipientId, tags: 'tech stuff'})
然后,您可以使用在首选项中找到的 messageId 来查询并找到所有对应的消息:
db.messages.find((type:'message', _id: { $in : [array of messageIds from prefs]}})
如果你想做一些事情,比如计算每个“标签”包含多少消息,这可能会有点棘手。如果只有少数标签,您只需将 .count()
添加到每个查询的查询末尾。如果它是数百或数千,那么您可能会使用 map/reduce 服务器端脚本或跟踪每个用户每个标签的消息计数的对象做得更好。
关于MongoDB/NOSQL : Best approach to handling read/unread status on messages,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4180817/