Предложения схемы уведомлений пользователей Mongoose / MongoDB

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

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

Вариант первый

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

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

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


person drinchev    schedule 01.04.2012    source источник
comment
Мне интересно, рассматривали ли вы notifications встроенный объект для каждого User документа. в принципе, вам вообще не нужна отдельная модель для уведомлений... Просто создайте объект для пользователя и обновите его, когда должны появиться уведомления.   -  person Augie Gardner    schedule 26.07.2016


Ответы (1)


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

Вариант 2. Мне не совсем понятна ваша стратегия - кажется излишним иметь эти 3 коллекции, но также вставлять список уведомлений по objectId, если вы уже ссылаетесь на пользователя по идентификатору в таблице уведомлений. Вы можете проиндексировать пользователя в таблице уведомлений, а затем удалить вложенный массив в таблице пользователей.

(EDIT) Вот еще одна стратегия для рассмотрения.

Три коллекции, которые выглядят так:

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]

Для уведомлений, предназначенных для одного пользователя, вставьте в Уведомления для этого пользователя. Для нескольких пользователей вставьте по одному для каждого пользователя (в качестве альтернативы вы можете сделать поле «кому» массивом и хранить _id всех получателей, а затем поддерживать другой список всех получателей, которые его прочитали). Чтобы отправить уведомление всем пользователям, вставьте в коллекцию Global Notifications. Когда пользователь прочитает его, добавьте _id своего пользователя в поле read_by. Итак, чтобы получить список всех непрочитанных уведомлений пользователя, вы делаете два запроса: один к уведомлениям и один к глобальным уведомлениям.

person mpobrien    schedule 10.04.2012
comment
Хорошо, для варианта 2, но я понял, что если я проиндексирую пользователя в коллекции уведомлений, у меня будут одни и те же записи уведомлений несколько раз для каждого пользователя..., например. ( { пользователь : 'Альфа', уведомление: 'Глобальное сообщение' }, { пользователь : 'Бета', уведомление : 'Глобальное сообщение' }. Так что это не тот подход, который мне нужен. Мне нужно минимальное количество информация хранится - person drinchev; 11.04.2012
comment
@drinchev, в этом случае было бы неплохо по-другому обрабатывать глобальные сообщения. я отредактировал свой комментарий, чтобы дать некоторые идеи по этому поводу. - person mpobrien; 17.04.2012
comment
Я не уверен, что объединение двух запросов очень удобно, так как я не смогу отсортировать их с помощью сортировки мангуста... Но спасибо;) - person drinchev; 17.04.2012
comment
Можно ли оставить отзыв о том, что вы сделали в конце? А что бы вы порекомендовали? - person Codii; 23.11.2012
comment
Пока нет отзывов... Я использовал вариант 2 из своего вопроса. Но в любом случае приложение так и не было запущено в производство, поэтому у меня нет проверенных плюсов и минусов. :) - person drinchev; 14.01.2014