MongoDB 用户通知方案建议

Eta*_*nor 3 mongoose mongodb mongoose-schema

我想知道用户/通知类型场景的最佳方案是什么,如下所示:

1 | 01-04-2020 | X | John liked your post2 
2 | 01-03-2020 | X | Mike and 9 other persons liked your post1
3 | 01-02-2020 |   | Rose and 2 other persons liked your post1
4 | 01-01-2020 |   | Bernard liked your post1

x = notification has not been read by the user yet
post1 = the same post in all the notifications
Run Code Online (Sandbox Code Playgroud)

假设我有一个通知集合,例如:

_id: ObjectID
receiver: ObjectID (User)
sender : ObjectID (User)
type: String ("post", "comment", etc...)
typeID: ObjectID (Post, Comment, etc...)
message: String
isRead : Boolean
timestamp: Date
Run Code Online (Sandbox Code Playgroud)

用户集合如下:

_id: ObjectID
username: String
.
.
.
email: String
Run Code Online (Sandbox Code Playgroud)

帖子收藏如:

_id: ObjectID
postedBy: ObjectID (User)
.
.
.
content: String
Run Code Online (Sandbox Code Playgroud)

喜欢的收藏,例如:

_id: ObjectID
type: String ("post", "comment", etc...)
typeID: ObjectID (Post, Comment, etc...)
likedBy: ObjectID (User)
Run Code Online (Sandbox Code Playgroud)
  • 2020 年 1 月 1 日,用户打开了通知面板。从他上次查看通知到今天,只有 1 人喜欢他的帖子1。
  • 2020 年 1 月 2 日,用户打开了通知面板。从他上次查看通知(2020 年 1 月 1 日)到当前日期,有 2 人喜欢了他的帖子1。
  • 2020 年 1 月 4 日,用户打开了通知面板。从他上次查看通知(2020 年 2 月 1 日)到当前日期,有 9 人喜欢他的帖子1,1 人喜欢他的帖子2。

我希望用户能够看到他之前的所有通知以及他尚未阅读的通知。如果用户对同一帖子有多个通知(自上次检查通知以来,有 X 个人喜欢他的帖子),我想将它们分组为 1 个通知(一旦他阅读了该分组通知,我会将所有通知标记为已读) )。

我怎样才能做到这一点?

如果您需要更多信息或者我不清楚,请告诉我。

谢谢


编辑:

我正在努力弄清楚如何聚合这些通知。我想我还需要某种读取日期标记来对分组并同时读取的通知进行分组,但也许我需要另一个集合来存储分组的通知?

Notification.aggregate([
        {
            $group: {
                _id: {
                    typeID : "$typeID",
                    receiver: "$receiver",
                    isRead: "$isRead"
                    // maybe something with a read date?
                },
                count: {$sum: 1}
            }
        }

])
Run Code Online (Sandbox Code Playgroud)

Ale*_*Dim 5

我想Mongo 大学的这篇文章可以回答你的问题。

至少使用两个集合:users而且notifications,你的用户_id字段不是类似的东西name,你将允许它们被重命名,那么拥有第三个集合是完美的likes,而不是像数组中的嵌入文档那样制作喜欢的东西:

用户架构:

  _id: ObjectID,
  likes: [{
     _id: ObjectID //like_id,
     other: "field"
  }]
Run Code Online (Sandbox Code Playgroud)

图案

通知:

_id: ObjectID
receiver: ObjectID (User)
sender : ObjectID (User)
type: {
        type: String,
        enum: ["Post", "Comment"] /** Use enum for avaliable values */
    },
typeID: {
    type: ObjectID, /** It's better if every ID field have an index */
    index: true, 
    unique: true
}
message: String
isRead : Boolean
timestamp: { 
   type: Date,
   default: Date.now /** Don't forget about default values, but check my advice below about $timestamps */
}
Run Code Online (Sandbox Code Playgroud)
  • 不确定您是否需要时间戳字段,对于我来说,最好使用{timestamps: true}选项。

  • 此外,每个字段都ObjectID应该被索引,如果您需要这个字段作为aggregation框架。这是一个完美的性能案例$lookup

我希望用户能够看到他之前的所有通知以及他尚未阅读的通知。

你需要一个compound索引,比如{sender:1, createdAt: -1, isRead: 1}

我想将它们分组为 1 个通知(一旦他阅读了该分组通知,我会将所有通知标记为已读)。

这是框架的工作aggregation,通过:

{
   $match: { query_criteria },

},
{
   $group: { query_group_by $notification.typeID }
}
Run Code Online (Sandbox Code Playgroud)

所以你的模式很好,可以做到这一点。顺便说一句,要测试您自己的查询,您可以使用MongoPlayground而不是生产数据库。

至于likes架构,由您决定,但也许最好将它们作为嵌入式(子)文档,例如:

邮政

_id: ObjectID
postedBy: ObjectID (User)
likes: [{
   /** Likes Sub-schema */
}]
content: String
Run Code Online (Sandbox Code Playgroud)

看一下mongoose 中的子模式模式。

希望它会对您有所帮助!