Mongodb / nosql: лучший подход к обработке статуса чтения / непрочитанного в сообщениях

StackOverflow https://stackoverflow.com/questions/4180817

Вопрос

Предположим, у вас есть большое количество пользователей (M) и большое количество документов (n), и вы хотите, чтобы каждый пользователь мог отмечать каждый документ как чтение или непрочитанное (как и любая система электронной почты). Как лучше всего представить это в MongoDB? Или любая другая база данных документов?

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

Какой самый эффективный способ запомнить статус чтения/непрочитанного по нескольким элементам?

Внедрение эффективной системы счетчиков «непрочитанных комментариев»

Обычно ответы включают в себя таблицу, в которой указано все, что пользователь читал: (т.е. кортежи идентификатора пользователя, идентификатор документа) с некоторыми возможными оптимизациями для отключения даты, позволяющей марке-все-читающему для вытирания базы данных и начать снова, зная, что все что угодно До этой даты «читать».

Итак, эксперты MongoDB / NOSQL, какие подходы вы видели на практике к этой проблеме и как они работали?

Это было полезно?

Решение

{
_id: messagePrefs_uniqueId,
type: 'prefs',
timestamp: unix_timestamp
ownerId: receipientId,
messageId: messageId,
read: true / false,
}

{
_id: message_uniqueId,
timestamp: unix_timestamp
type: 'message',
contents: 'this is the message',
senderId: senderId,
recipients: [receipientId1,receipientId2]
}

Скажем, у вас есть 3 сообщения, для которых вы хотите получить предпочтения, вы можете получить их через что -то вроде:

db.messages.find({
messageId : { $in : [messageId1,messageId2,messageId3]},
ownerId: receipientId, 
type:'prefs'
})

Если все, что вам нужно, это прочитать/не прочитать, вы можете использовать это с возможностями повышения MongoDB, поэтому вы не создаете Prefs для каждого сообщения, если только пользователь фактически не читает его, то в основном вы создаете объект Prefs со своим собственным уникальным идентификатором и поднимаете его в MongoDB Анкет Если вы хотите больше гибкости (например, теги или папки, вы, вероятно, захотите сделать Pref для каждого получателя сообщения. Например, вы можете добавить:

tags: ['inbox','tech stuff']

к объекту Prefs, а затем, чтобы получить все предпочтения всех сообщений, помеченных «техническими вещами», вы пойдете что -то вроде:

db.messages.find({type: 'prefs', ownerId: recipientId, tags: 'tech stuff'})

Затем вы можете использовать сообщения, которые вы найдете в Prefs для запроса, и найти все сообщения, которые соответствуют:

db.messages.find((type:'message', _id: { $in : [array of messageIds from prefs]}})

Это может быть немного сложно, если вы хотите сделать что -то вроде подсчета того, сколько сообщений каждый «тег» содержит эффективно. Если это всего лишь несколько тегов, вы можете просто добавить .count() до конца вашего запроса для каждого запроса. Если это сотни или тысячи, то вы можете добиться большего успеха с помощью сценария на стороне сервера MAP/уменьшения сервера или, возможно, объекта, который отслеживает количество сообщений на тег на пользователя.

Другие советы

Если вы храните только простое логическое значение, например, Read/Unroid, другой метод заключается в том, чтобы встроить массив в каждый документ, который содержит список пользователей, которые его прочитали.

{
  _id: 'document#42',
  ...
  read_by: ['user#83', 'user#2702']
}

Затем вы должны иметь возможность индексировать это поле, создавая быстрые запросы для документов, читаемых за пользователем и пользователями, которые читают документ.

db.documents.find({read_by: 'user#83'})

db.documents.find({_id: 'document#42}, {read_by: 1})

Тем не менее, я считаю, что обычно запрашиваю все документы, которые нет был прочитал конкретный пользователь, и я не могу придумать какого -либо решения, которое может использовать индекс в этом случае. Я подозреваю, что невозможно сделать это быстро, не имея обоих read_by а также unread_by массивы, так что каждый пользователь включен в каждый документ (или таблицу присоединения), но это будет иметь большую стоимость хранения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top