Лента социальной активности - лучший подход для ограниченных коллекций в MongoDB?
Я работаю над системой подачи социальной активности, очень похожей на 10Gen Socialite Project, который запущен в производство уже несколько лет. У меня есть новый вариант использования, в котором мне нужно хранить хронологически упорядоченный список действий для пользователя, где список действий должен:
- содержит только последние вставленные N элементов
- не вставлять дубликаты семантически эквивалентных элементов
- позволяют просматривать результаты.
До сих пор я придумал два подхода к решению этой проблемы, но оба, кажется, имеют неприятные ограничения.
Первый подход (который близко соответствует моим другим коллекциям) состоит в том, чтобы иметь одну коллекцию, содержащую один документ для каждого действия, проиндексированный по идентификатору пользователя. Например:
{
"owner": {
"type": "user",
"id" : "1234"
},
"activity": {
"published": "2013-09-27T17:08:26+00:00",
"actor": {
"type": "elastic-search-node",
"id": "2"
},
"verb": "recommend",
"object": {
"type": "review",
"id": "1093773"
}
"uuid": "6d70eaa4-0766-4949-971d-98740cb9eca1"
}
}
Каждый раз, когда я получаю новое действие для данного пользователя, я вставляю документ, как указано выше, с тем же условием "владелец", но с другим предложением "действие". Однако я не уверен в самом эффективном способе обработки моих вкладышей. Учитывая критерии выше, один подход псевдокода будет:
results = collection.update(
{
'owner.id':'1234',
'activity.verb':'recommend',
'activity.object.type':'review',
'activity.object.id':'1093773'
},
the_activity,
upsert:true)
# count documents for owner.id = 1234
# if count > max_documents, delete oldest document
Проблема этого подхода состоит в том, что для завершения вставки и удаления может потребоваться до 3 операций с базой данных. Тем не менее, использование 'upsert' заботится о предотвращении дубликатов, и мы можем использовать сгенерированный ObjectID для временных запросов и разбиения на страницы.
Другой подход, на который я смотрел, похож на подход FanoutOnWriteSizedBuckets в Socialite. В этом случае список действий сохраняется в массиве максимального размера в качестве поддокумента, индексируемого по идентификатору пользователя. Например:
{
"owner" : {"type":"user", "id":"1234"},
"feed" : [
{"_id" : ObjectId("...da7"), "activity" : ...},
{"_id" : ObjectId("...dc1"), "activity" : ...},
{"_id" : ObjectId("...dd2"), "activity" : ...}
]
}
В этом случае запросы также довольно просты, но, опять же, вставки проблематичны. Я рассмотрел использование различных методов и комбинаций $update, $push, $addToSet, $ne, $each и т. Д., Но ни один из них, по-видимому, не в состоянии обеспечить более эффективное предотвращение дублирования операций вставки и удаления, чем выше.
Кто-нибудь может предложить подход для решения этого варианта использования?
Спасибо!
(x-отправлено в группу пользователей mongodb)РЕШЕНО: https://groups.google.com/forum/