MongoDB хранит пользовательские данные об общих объектах коллекции - PullRequest
3 голосов
/ 07 ноября 2011

Я разрабатываю приложение, которое обрабатывает RSS-каналы с использованием MongoDB. В настоящее время мои коллекции таковы:

Entry
fields: content, feed_id, title, publish_date, url

Feed
fields: description, title, url

User
fields: email_address
subscriptions (embedded collection; fields: feed_id, tags)

Пользователь может подписаться на каналы, которые связаны со встроенной коллекцией подписок. Из подписок я могу получить список всех каналов, которые должен видеть пользователь, а также соответствующие записи.

Как хранить информацию о состоянии записи (isRead, isStarred и т. Д.), Относящуюся к пользователю? Когда пользователь просматривает запись, мне нужно записать isRead = 1. Два общих запроса, которые мне нужно выполнить, это:

  • Найти все записи для определенного канала, где isRead = 0 или статус в настоящее время отсутствует
  • Для конкретного пользователя пометьте все записи до даты публикации isRead = 1 (это могут быть сотни или даже тысячи записей, поэтому это должно быть эффективно)

1 Ответ

2 голосов
/ 15 ноября 2011

Хм, это сложно!

Имеет смысл хранить записи для непрочитанных записей и удалять их, когда они читаются.Я основываю это на предположении, что будет больше прочитанных постов, чем непрочитанных для каждого отдельного пользователя, так что вы могли бы также не иметь документов для всех этих уже прочитанных записей, сидящих в вашей БД вечно.Это также облегчает отсутствие необходимости беспокоиться об ограничении размера документа в 16 МБ, если вам не нужно тащить годами историю с вами повсюду.

Для помеченных записей я бы просто добавил массив EntryObjectIds для пользователя.Не нужно делать эти подписки специфичными;будет намного проще получить список элементов, которые пользователь пометил таким образом.

Для непрочитанных записей это немного сложнее.Я бы по-прежнему добавил его в виде массива, но для удовлетворения ваших потребностей в способности быстро пометить записи как прочитанные до определенной даты, я бы денормализовал и сохранил дату публикации вместе с Entry ObjectId в новом UnreadEntry.document.

User
fields: email_address, starred_entries[]
subscriptions (embedded collection; fields: feed_id, tags, unread_entries[])

UnreadEntry
fields: id is Entry ObjectId, publish_date

Вы должны помнить о предельном количестве документов, но 16 МБ - это чертовски много непрочитанных записей / каналов, поэтому будьте реалистичны в отношении того, стоит ли беспокоиться об этом ограничении.(Если это так, было бы довольно просто вывести подписки User.subs на его собственный документ.)

Теперь оба ваших запроса довольно легко написать:

Все записи для определенногонепрочитанный фид: user.subscriptions.find(feedID).unread_entries

Пометить все записи до даты публикации: user.subscriptions.find(feedID).unread_entries.where(publish_date.lte => my_date).delete_all

И, конечно, если вам просто нужно пометить все записи в фиде какчитать, это очень просто: user.subscriptions.find(feedID).unread_entries.delete_all

...