Mongoose / MongoDB Предложения по схеме уведомлений пользователей - PullRequest
16 голосов
/ 01 апреля 2012

Мне было интересно, какова лучшая схема для сценария типа пользователя / уведомления, подобного следующему:

  • У вас есть несколько пользователей.
  • У вас есть несколько уведомлений, которые могут быть для одного пользователя, для некоторых пользователей или для всех пользователей.
  • Вам нужна запись о прочтении уведомления в хранилище, чтобы узнать, прочитал ли пользователь уведомление или нет.

Вариант один

Встроенная схема уведомлений

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 для каждого встроенного Уведомления
  • Несколько записей уведомлений для каждого пользователя (несколько данных в базе данных)
  • Гигантский встроенный документ (я читал кое-что о предельном размере <4 МБ) </li>
  • Поскольку это встроенный документ - (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. Может кто-нибудь предложить лучшую схему?

Заранее спасибо, и я прошу прощения за длинный пост, но я думаю, что не могу объяснить это проще.

Ответы [ 2 ]

12 голосов
/ 11 апреля 2012

Вариант 1 выглядит так, как будто он, вероятно, приведет к чрезмерному росту и перемещению документов, что отрицательно скажется на производительности, поскольку большинство ваших записей будут идти во встроенный документ (Уведомления).

Вариант 2 Я не совсем понимаю вашу стратегию - кажется, что эти 3 коллекции избыточны, но также встраивают список уведомлений по 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» массивом и сохранить _ids всех получателей, а затем вести еще один список всех получателей, которые его прочитали).Чтобы отправить уведомление всем пользователям, вставьте в коллекцию глобальных уведомлений.Когда пользователь читает его, добавьте _id своего пользователя в поле read_by.Таким образом, чтобы получить список всех непрочитанных уведомлений пользователя, вы делаете два запроса: один к уведомлениям, а другой к глобальным уведомлениям.

0 голосов
/ 22 июня 2017
`// 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',
  }]
});`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...