Как сгруппировать по _id и стране?

Мне нужно сгруппировать по _id и странам. Мне удалось сгруппировать по _id, но я хотел бы знать, как сгруппировать страны в этих _id и вернуть количество для каждой страны.

Я использую структуру агрегации. Все идет нормально.

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"
            }
        ]
    }
]

person Christian Fazzini    schedule 26.07.2012    source источник


Ответы (2)


Я изменил $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 } },
  ]
}
person Ross    schedule 26.07.2012

Из документации

$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']
person Nigel Thorne    schedule 26.07.2012