【问题标题】:Mongoose / MongoDB User notifications scheme suggestionsMongoose / MongoDB 用户通知方案建议
【发布时间】:2012-04-15 11:17:06
【问题描述】:

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

  • 您有多个用户。
  • 您有多个通知,可能针对单个用户、某些用户或所有用户。
  • 您需要存储中的通知“已读”条目,以了解用户是否已阅读通知。

选项一

嵌入式通知方案

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() 会将通知显示为数组对象。

缺点:

  • 为每个用户创建通知时,您需要对每个嵌入的通知执行 .push
  • 每个用户的多个通知条目(数据库中的多个数据)
  • 巨大的嵌入式文档(我读过一些关于
  • 由于它是嵌入式文档 - ( 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 个收藏,而不是其中的一个(选项一只有一个收藏)
  • 您每次访问该集合时都有 3 个查询。

问题

  1. 您认为这两者中最好的方案是什么?
  2. 我是否缺少某些东西或某种基本的 NoSQL 知识?
  3. 谁能提出更好的方案?

提前谢谢你,很抱歉发了这么长的帖子,但我想我不能更简单地解释它。

【问题讨论】:

  • 我想知道您是否为每个 User 文档考虑了一个 notifications 嵌入对象。基本上,您根本不需要单独的通知模型......只需在用户上拥有一个对象,并在需要出现通知时更新它。

标签: mongodb mongoose


【解决方案1】:

选项 1 看起来可能会导致大量过度的文档增长和移动,这对性能不利,因为您的大部分写入都将发送到嵌入式文档(通知)。

选项 2 我对您的策略并不完全清楚 - 如果您已经在通知表中按 ID 引用用户,那么拥有这 3 个集合似乎是多余的,但还嵌入了 objectId 通知列表。您可以在 Notifications 表中对 user 进行索引,然后消除 Users 表中的嵌套数组。

(编辑) 这是另一个需要考虑的策略。

三个类似这样的集合:

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,然后维护另一个已阅读它的所有收件人的列表)。要向所有用户发送通知,请插入 Global Notifications 集合。当用户阅读它时,将其用户的 _id 添加到 read_by 字段。 因此,要获取用户所有未读通知的列表,您需要执行两个查询:一个查询通知,一个查询全局通知。

【讨论】:

  • 好,对于选项 2,但我发现如果我在 Notifications 集合中对 User 进行索引,我将为每个用户多次拥有相同的通知条目...,例如( { user : 'Alpha', notification: 'Global message' }, { user : 'Beta', notification : 'Global message' }。所以这也不是我正在寻找的方法。我想要最少的存储的信息
  • @dinchev 在这种情况下以不同方式处理全局消息可能是个好主意。我编辑了我的评论以提供一些关于此的想法。
  • 我不确定组合这两个查询是否非常方便,因为我无法使用 mongoose sort 对它们进行排序...但是谢谢 ;)
  • 是否可以对您最后所做的事情进行反馈?你会推荐什么?
  • 到目前为止没有反馈...我使用了我的问题中的选项 2。但无论如何,该应用程序从未投入生产,所以我没有任何经过测试的优缺点。 :)
【解决方案2】:
// namespace like a channel
// we have a notification from specific channel or namespace
const NamespaceSchema = new Schema({
  name: {
    type: String,
    unique: true,
    required: true
  },
  author: {
    type: String,
    required: true
  },
  createdAt: {
    type: Boolean,
    default: Date.now()
  },
  notifications: [{
    type: Schema.Types.ObjectId,
    ref: 'Notification',
  }]
});

// the notification schema have a subscribers to specific notification (objectId)
//
const NotificationSchema = new Schema({
  title: {
    type: String
  },
  message: {
    type: String
  },
  read: {
    type: Boolean,
    default: false
  },
  subscribers: [{
    type: Schema.Types.ObjectId,
    ref: 'Subscriber'
  }],
  createdAt: {
    type: Date,
    default: Date.now()
  }
});
// subscribers subscribe to a namespace or channel
const SubscriberSchema = new Schema({
  subscriber: {
    type: String,
    required: true
  },
  namespaces: [{
    type: Schema.Types.ObjectId,
    ref: 'Namespace',
  }]
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    相关资源
    最近更新 更多