MongoDB, вернуть последний документ для каждого user_id в коллекции - PullRequest
4 голосов
/ 01 марта 2011

В поисках функциональности, аналогичной Postgres 'Distinct On.

Иметь коллекцию документов {user_id, current_status, date}, где статус - это просто текст, а дата - это Дата. Все еще на ранних стадиях оборачивания моей головы вокруг монго и ощущения лучшего способа сделать вещи.

Является ли mapreduce лучшим решением здесь, карта генерирует все, а сокращение сохраняет запись последнего, или есть встроенное решение без удаления mr?

Ответы [ 3 ]

0 голосов
/ 01 марта 2011

Текущее решение, которое, кажется, работает хорошо.

map = function () {emit(this.user.id, this.created_at);}

//We call new date just in case somethings not being stored as a date and instead just a string, cause my date gathering/inserting function is kind of stupid atm

reduce = function(key, values) { return new Date(Math.max.apply(Math, values.map(function(x){return new Date(x)})))}


res = db.statuses.mapReduce(map,reduce);
0 голосов
/ 01 марта 2011

Другим способом достижения того же результата было бы использование команды group, которая является своего рода ярлыком mr, который позволяет вам агрегировать по определенному ключу или набору ключей. В вашем случае это будет выглядеть так:

db.coll.group({ key : { user_id: true },
                reduce : function(obj, prev) { 
                           if (new Date(obj.date) < prev.date) { 
                             prev.status = obj.status; 
                             prev.date = obj.date; 
                           }
                         },
              initial : { status : "" }
}) 

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

0 голосов
/ 01 марта 2011

Существует команда distinct , однако я не уверен, что это то, что вам нужно. Distinct - это своего рода команда запроса, и у многих пользователей вы, вероятно, захотите свернуть данные не в режиме реального времени.

Map-Reduce, вероятно, является одним из способов пойти сюда.

Фаза карты: Ваш key будет просто идентификатором. Ваш value будет выглядеть примерно так: {current_status:'blah',date:1234}.

Фаза сокращения: При наличии массива значений вы можете получить самое последнее и вернуть только его.

Для оптимальной работы вам, вероятно, захочется взглянуть на новую функцию с 1.8.0. функция «повторного уменьшения» . Позволит обрабатывать только новые данные вместо повторной обработки всей коллекции статусов.

Другой способ сделать это - создать «самую последнюю» коллекцию и привязать вставку статуса к этой коллекции. Поэтому, когда вы вставляете новый статус для пользователя, вы обновляете его «самый последний».

В зависимости от важности этой функции, вы можете сделать обе вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...