我想知道什么是用户/通知类场景的最佳方案,如下所示:
您有多个用户。
您有多个通知,可能是针对单个用户、某些用户或所有用户的。
您需要在存储器中有一个通知“读取”条目,以知道用户是否已读取该通知。
方案一
嵌入式通知方案

Notifications = new Schema ( {
    message : String,
    date : { type : Date, default: Date.now() }
    read : { type: Boolean, default : false }
});

User = new Schema( {
    username : String,
    name : String,
    notifications : [Notifications]
});

赞成的意见:
显示数据非常容易,因为调用user.find()将以数组对象的形式显示通知。
欺骗:
当您为每个用户创建通知时,您需要这样做。推送到每个嵌入的通知
每个用户有多个通知条目(数据库中有多个数据)
巨大的嵌入式文档(我读到了一些小于4MB的限制)
因为它是一个嵌入的文档(mongoose documentarray),所以不能搜索或跳过。每次访问用户时都加载每个通知。
方案二
填充(类似dbref)对象
Notification = new Schema ({
    message : String,
    date : { type : Date, default : Date.now() }
});

UserNotification = new Schema ({
    user : { type : Schema.ObjectId, ref : 'User' },
    notification : { type : Schema.ObjectId, ref : 'Notification' },
    read : { type : Boolean, default : false }
});

User = new Schema( {
    username : String,
    name : String,
    notifications : [ { type : Schema.ObjectID, ref : 'UserNotification' } ]
});

赞成的意见:
最适合查询
无重复数据
支持大量通知
欺骗:
您有3个集合,而不是1个集合(选项1只有一个集合)
每次访问集合时都有3个查询。
问题
你认为这两个最好的方案是什么?
我是否缺少一些基本的NoSQL知识?
有人能提出更好的方案吗?
谢谢你,我对这篇长文章感到抱歉,但我想我不能简单地解释。

最佳答案

选项1看起来可能会导致大量文档过度增长和移动,这对性能不利,因为您的大部分写入操作都将指向嵌入的文档(通知)。
选项2我不完全清楚您的策略-拥有这3个集合似乎是多余的,但是如果您已经在通知表中按ID引用用户,那么还可以嵌入一个objectid通知列表。可以在通知表中对用户进行索引,然后消除用户表中的嵌套数组。
(编辑)
这是另一个需要考虑的策略。
三个类似的集合:

Users:
   _id: objectid
   username : string
   name: string

Notifications:
   _id:  objectid
   to (indexed):   objectid referencing _id in "users" collection
   read: boolean

Global Notifications:
   _id: objectid
   read_by: [objectid referencing _id in users]

对于针对单个用户的通知,请插入到该用户的通知中。对于多个用户,为每个用户插入一个(或者,您可以使“to”字段成为一个数组,并存储所有收件人的ID,然后维护所有已读过它的收件人的另一个列表)。若要向所有用户发送通知,请插入到全局通知集合中。当用户读取时,将其用户的ID添加到“读取方式”字段中。
因此,要获取用户所有未读通知的列表,需要执行两个查询:一个查询到通知,一个查询到全局通知。

10-01 23:52
查看更多