Для получения значений дочерних элементов используйте Mongo Map / Reduce. - PullRequest
0 голосов
/ 09 августа 2011

У меня есть коллекция монго, я хочу получить общее значение 'number_of_ad_clicks' по заданному названию места, отметке времени и идентификатору варианта. Потому что у нас большие данные, поэтому было бы лучше использовать карту / уменьшить. Могут ли парни дать мне какое-нибудь предложение?

Вот моя коллекция в формате json

{ "_id" : ObjectId( "4e3c280ecacbd1333b00f5ff" ),
  "timestamp" : "20110805",
  "variants" : { "94" : { "number_of_ad_clicks" : 41,
      "number_of_search_keywords" : 9,
      "total_duration" : 0,
      "os" : { "os_2" : 2,
        "os_1" : 1,
        "os_0" : 0 },
      "countries" : { "ge" : 6,
        "ca" : 1,
        "fr" : 8,
        "uk" : 4,
        "us" : 6 },
      "screen_resolutions" : { "(320, 240)" : 1,
        "(640, 480)" : 5,
        "(1024, 960)" : 5,
        "(1280, 768)" : 5 },
      "widgets" : { "widget_1" : 1,
        "widget_0" : 0 },
      "languages" : { "ua_uk" : 8,
        "ca_en" : 2,
        "ca_fr" : 2,
        "us_en" : 5 },
      "search_keywords" : { "search_keyword_8" : 8,
        "search_keyword_5" : 5,
        "search_keyword_4" : 4,
        "search_keyword_7" : 7,
        "search_keyword_6" : 6,
        "search_keyword_1" : 1,
        "search_keyword_3" : 3,
        "search_keyword_2" : 2 },
      "number_of_pageviews" : 18,
      "browsers" : { "browser_4" : 4,
        "browser_0" : 0,
        "browser_1" : 1,
        "browser_2" : 2,
        "browser_3" : 3 },
      "keywords" : { "keyword_5" : 5,
        "keyword_4" : 4,
        "keyword_1" : 1,
        "keyword_0" : 0,
        "keyword_3" : 3,
        "keyword_2" : 2 },
      "number_of_keyword_clicks" : 83,
      "number_of_visits" : 96 } },
  "site_name" : "fonter.com",
  "number_of_variants" : 1 }

Вот моя попытка. но не удалось. Он моя попытка.

m = function() {
    emit(this.query, {variants: this.variants});
}

r = function(key , vals) {
    var clicks = 0 ;
    for(var i = 0; i < vals.length(); i++){
        clicks = vals[i]['number_of_ad_clicks'];
    }
    return clicks;
}
res = db.variant_daily_collection.mapReduce(m, r, {out : "myoutput", "query":{"site_name": 'fonter.com', 'timestamp': '20110805'}})
db.myoutput.find()

Может кто-нибудь предложить?

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

res = db.variant_daily_collection.mapReduce(map, reduce, {out : "myoutput", "query":{"site_name": 'facee.com', 'timestamp': '20110809', 'variant_id': '305'}})
db.myoutput.find()

1 Ответ

0 голосов
/ 09 августа 2011

Функция emit испускает значения key и value.

Если вы привыкли к SQL, думайте о key как о GROUP BY и value как о SUM(), AVG(), etc..

В вашем случае вы хотите "группировать по": site_name, метка времени и вариант ID.Похоже, что у вас может быть более одного варианта, поэтому вам нужно будет перебрать варианты, например:

map = function() {
  for(var i in variants){
    var key = {};
    key.timestamp = this.timestamp;
    key.site_name = this.site_name;
    key.variant_id = i; // that's the "94" string.

    var value = {};
    value.clicks = this.variants[i].number_of_ad_clicks;

    emit(key, value);
  }
}

Функция Reduce получит массив значений, каждое из которых будет выглядеть как { clicks: 41 }.Функция должна вернуть один объект, который выглядит одинаково.

Так что если вы получите values = [ {clicks:21}, {clicks:10}, {clicks:5} ], вы должны вывести {clicks:36}.

Итак, вы делаете что-то вроде этого:

reduce = function(key , vals) {
    var returnValue = { clicks: 0 }; // initializing to zero
    for(var i = 0; i < vals.length(); i++){
        returnValue.clicks += vals[i].clicks;
    }
    return returnValue;
}

Обратите внимание, что value из map имеет ту же форму, что и возврат из reduce.

...