Как сгруппировать по _id и стране?
-
11-12-2019 - |
Вопрос
Мне нужно сгруппировать по _id и странам.Мне удалось сгруппировать по _id
, но хотелось бы знать, как сгруппировать страны в этих _id
s и верните счетчик для каждой страны.
Я использую структуру агрегации.Все идет нормально.
conn = Mongo::Connection.new
db = conn['foobar_development']
cmd = {
aggregate: 'live_daily_stats',
pipeline: [
{ '$project' => {
:metacontent => 1,
:visits => 1,
} },
{ '$unwind' => '$visits' },
{ '$match' => { 'visits.minute' => { '$gt' => 224 } } },
{ '$sort' => { 'visits.minute' => 1 } },
{ '$group' => {
:_id => '$_id',
:visits => { '$push' => '$visits' },
:visits_count => { '$sum' => 1 },
:metacontent => { '$addToSet' => '$metacontent' },
}
},
{ '$sort' => { 'visits_count' => -1 } },
]
}
res = db.command(cmd)['result']
Следующие результаты возвращаются:
[
[0] {
"_id" => "20120726/foobar/song/custom-cred",
"visits" => [
[0] {
"country_name" => "UK",
"iso_two_letter_country_code" => "UK",
"referer" => "http://localhost:3000/",
"minute" => 59,
"token_id" => "134326199711wfryhpdq"
},
[1] {
"country_name" => "UK",
"iso_two_letter_country_code" => "UK",
"referer" => "http://localhost:3000/",
"minute" => 59,
"token_id" => "134326199711wfryhpdq"
},
[2] {
"country_name" => "US",
"iso_two_letter_country_code" => "US",
"referer" => "http://localhost:3000/",
"minute" => 59,
"token_id" => "134326199711wfryhpdq"
}
],
"visits_count" => 1,
"metacontent" => [
[0] {
"date" => "20120726"
}
]
},
[1] {
"_id" => "20120725/foobar/song/test-pg3-long-title-here-test-lorem-ipsum-dolor-lo",
"visits" => [
[0] {
"country_name" => "UK",
"iso_two_letter_country_code" => "UK",
"referer" => "http://localhost:3000/",
"minute" => 58,
"token_id" => "13432600883knjzcbic"
}
],
"visits_count" => 1,
"metacontent" => [
[0] {
"date" => "20120725"
}
]
}
]
Решение
Я изменил $group
объединить оба _id
и country_name
:
cmd = {
aggregate: 'live_daily_stats',
pipeline: [
{ '$project' => {
:metacontent => 1,
:visits => 1,
} },
{ '$unwind' => '$visits' },
{ '$match' => { 'visits.minute' => { '$gt' => 224 } } },
{ '$sort' => { 'visits.minute' => 1 } },
{ '$group' => {
:_id => { '$add' => ['$_id', '$visits.country_name']},
:visits => { '$push' => '$visits' },
:visits_count => { '$sum' => 1 },
:metacontent => { '$addToSet' => '$metacontent' },
}
},
{ '$sort' => { 'visits_count' => -1 } },
]
}
Другие советы
От документация
Группа $ Group документирует вместе с целью расчета совокупных значений на основе сбора документов.Практически, группа часто поддерживает такие задачи, как обычные представления страниц для каждой страницы на веб -сайте ежедневно.
Вывод $group зависит от того, как вы определяете группы.Начните с указания идентификатора (т.е.Поле _id) для группы, которую вы создаете с помощью этого конвейера.Вы можете указать одно поле из документов в трубопроводе, ранее вычисленного значения или заполнительного ключа, состоящего из нескольких входящих полей.
В каждом групповом выражении должно быть указано поле _id.Вы можете указать поле _ID как ссылку на путь пунктирного поля, документ с несколькими полями, заключенными в фигурные скобки (т.{ и }), или постоянное значение.
Я бы попробовал сначала сгруппировать как по _id, так и по стране (позволяя вам выполнить желаемый подсчет), а затем сгруппировать результат только по _id, чтобы получить нужную структуру.
Обновлено:
Я думал что-то вроде этого..но у меня нет настройки env, чтобы это проверить..
conn = Mongo::Connection.new
db = conn['foobar_development']
cmd = {
aggregate: 'live_daily_stats',
pipeline: [
{ '$project' => {
:metacontent => 1,
:visits => 1,
} },
{ '$unwind' => '$visits' },
{ '$match' => { 'visits.minute' => { '$gt' => 224 } } },
{ '$sort' => { 'visits.minute' => 1 } },
{ '$group' => {
:_id => {'$_id','$visits.iso_two_letter_country_code'},
:page_id => '$_id',
:visits_count => { '$sum' => 1 },
.... whatever you want ...
:metacontent => { '$addToSet' => '$metacontent' },
}
},
{ '$group' => {
:_id => '$page_id',
.... whatever you want ...
}
},
{ '$sort' => { 'visits_count' => -1 } },
]
}
res = db.command(cmd)['result']