Стратегии для агрегации в реальном времени в MongoDB - PullRequest
7 голосов
/ 27 апреля 2011

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

  • Twitter's Rainbird : суммы в реальном времени, иерархически увеличивающиеся счетчики на ключах. Cassandra.
  • Yahoo S4 и source : Пока точно не знаю, как это работает, но похоже, что это сокращение карты в реальном времени. Таким образом, в основном, для каждой добавленной записи вы передаете ее в маппер, она преобразует ее в хеш и отправляет ее для интеграции в документ отчета.
  • http://www.slideshare.net/dacort/mongodb-realtime-data-collection-and-stats-generation
  • Hummingbird

Основной подход к выполнению сумм заключается в атомарном увеличении ключей документа для каждой новой поступающей записи для кэширования общих запросов:

Stats.collection.update({"keys" => ["a", "b", "c"]}, {"$inc" => {"counter_1" => 1, "counter_2" => 1"}, "upsert" => true);

Это не работает для агрегатов, кроме сумм. У меня вопрос, можно ли сделать что-то подобное для средних , min и max в mongodb?

Скажем, у вас есть такой документ:

{
  :date => "04/27/2011",
  :page_views => 1000,
  :user_birthdays => ["12/10/1980", "6/22/1971", ...] # 1000 total
}

Не могли бы вы сделать какую-нибудь атомарную или оптимизированную операцию в реальном времени, которая сгруппировала бы дни рождения в нечто вроде этого?

{
  :date => "04/27/2011",
  :page_views => 1000,
  :user_birthdays => ["12/10/1980", "6/22/1971", ...], # 1000 total
  :average_age => 27.8,
  :age_rank => {
    "0 to 20" => 180,
    "20 to 30" => 720,
    "30 to 40" => 100,
    "40 to 50" => 0
  }
}

... точно так же, как вы можете сделать Doc.collection.update({x => 1}, {"$push" => {"user_birthdays" => "12/10/1980"}}), чтобы добавить что-то в массив и не загружать документ, можете ли вы сделать что-то подобное для усреднения / объединения массива? Есть ли что-то в этом роде, что вы используете для агрегирования в реальном времени?

MapReduce используется для выполнения заданий пакетной обработки. Я ищу шаблоны для чего-то вроде карты-сокращения в реальном времени для:

  1. Средние значения : каждый раз, когда вы помещаете новый элемент в массив в mongodb, как лучше всего усреднить эти значения в режиме реального времени?
  2. Группировка : если вы группируете возраст по 10-летним скобкам и у вас есть массив возрастов, как вы могли бы оптимально обновить счетчик для каждой группы при обновлении документа с новым возрастом? скажем, массив возрастов будет постоянно выдвигаться / вытягиваться.
  3. Мин. / Макс. : Какими способами можно вычислить и сохранить мин. / Макс. Массив возрастов в этом документе?

Ответы [ 2 ]

5 голосов
/ 02 мая 2011

Не могли бы вы выполнить какую-нибудь атомарную или оптимизированную / в режиме реального времени операцию, которая сгруппировала бы дни рождения примерно так:

Похоже, вы добавили два поля age_rank, average_age.Это эффективно рассчитанные поля, основанные на данных, которые у вас уже есть.Если бы я дал вам документ с просмотром страниц и днями рождения пользователей, для клиентского кода было бы очень просто найти минимальное / максимальное, среднее и т. Д.

Мне кажется, что вы запрашиваете MongoDB длявыполнить агрегирование для вас на стороне сервера.Но вы добавляете ограничение, что вы не хотите использовать Map / Reduce?

Если я правильно понимаю ваш вопрос, вы ищете что-то, что вы можете сказать "добавить этоэлемент в массив и все зависимые элементы обновляются сами "?Вы не хотите, чтобы читатели выполняли какую-либо логику, вы хотите, чтобы все происходило «волшебным образом» на стороне сервера.

Таким образом, есть три различных способа решения этой проблемы, но в настоящее время доступен только один из них:

  1. Напишите эту логику на стороне клиента.Это не похоже на решение, которое вы хотите, но оно будет работать.Если у вас есть базовые данные, выполнение max / min / med / avg должно быть довольно тривиальным на большинстве языков.
  2. Использование новых функций для Aggregation .Это не запланировано до 1.9.x.Улучшенная агрегация позволит извлекать данные, которые вы ищете, однако вам все равно придется писать соответствующие запросы.Базовая БД по-прежнему не содержит данных, которые вы ищете.
  3. Вам нужно триггеров .Если вы действительно хотите, чтобы БД всегда была согласованной и содержала сводные данные, то это то, что вам нужно.Тем не менее, функция триггеров еще не существует.

К сожалению, ваш единственный вариант сейчас # 1.К счастью, я знаю нескольких людей, которые успешно используют опцию №1.

1 голос
/ 27 апреля 2011

Запланирована работа для предстоящего нестабильного выпуска 1.9.x, который может иметь агрегаты.

См .: https://jira.mongodb.org/browse/SERVER-447

Конечно, это может привести к более позднему выпуску /

...