2012-01-26 70 views
1

我想彙總博客中所有用戶的名稱,這些用戶已經回覆了對方。我有記載如下:訪問MongoDB中的關聯數組/對象MapReduce

{ 
    "_id" : ObjectId("4ee9ada4edfb941f3400ba63"), 
    "thread" : "Millenium - Niels Arden Oplev", 
    "author" : "kilny17", 
    "parent_count" : 0, 
    "parents" : [ ], 
    "child_count" : 2, 
    "date" : ISODate("2010-04-20T21:14:00Z"), 
    "message" : "I don't think so...", 
    "children" : [ 
      { 
        "date" : ISODate("2010-04-20T21:21:00Z"), 
        "author" : "Kissoon" 
      }, 
      { 
        "date" : ISODate("2010-04-20T21:49:00Z"), 
        "author" : "Twain" 
      } 
    ] 
} 

我試圖返回,每個作者,MapReduced對象,如:

{ "_id" : "kilny17", 
"value" : { 
    "author" : "kilny17", 
    "connections" : { 
      "Kissoon" : 1, 
      "Twain" : 1 } 
    } 
} 

此代碼的工作對於一個擁有僅1兒童元素的每個記錄孩子,但沒有更多:

function mapf() 
    { 
     var count = this['child_count']; 

     if (count > 0){ 
      var m_author = this.author; 

      this['children'].forEach(function(c){ 

        var connect = {'name':c['author'], 'appears':1}; 
        emit(m_author, {'author':m_author, 'connections':connect});     
      }); 
     };   
    } 

    function reducef(key, values) 
    { 
     var connects = new Object();   
     var r = {'author':key, 'connections':connects, 'weight':0}; 

     values.forEach(function(v) 
     { 
      c_name = v['connections'].name; 
      if (c_name == null) 
       c_name = 'Null_name'; 

      if (r['connections'][c_name] != null) 
       r['connections'][c_name] += v['connections']['appears']; 
      else 
       r['connections'][c_name] = v['connections']['appears']; 

     }); 

     return r;   
    } 

對於任何記錄(如給出的例子)超過1名兒童,作者姓名都沒有找到,我得到一個縮小的記錄,像這樣(NB有另一篇文章通過與孩子DarkKnight3657):

{ "_id" : "kilny17", "value" : { "author" : "kilny17", "connections" : { "DarkKnight3657" : 1, "Null_name" : null } } } 

任何人有任何想法,爲什麼作者的名字不是從對象讀取?

感謝

回答

0

正如克里斯曾建議,我用的解決辦法是改變對象到一個數組:

function mapf() 
    { 
     if (this['child_count'] > 0){ 

      var m_author = this.author; 
      if (m_author == '') 
       m_author = 'Unknown_author'; 

      var connect = []; 
      var weight = 0; 

      for (c in this['children']){ 
       c_name = this['children'][c]['author']; 
       found = false; 
       for (i in connect){ 
        if (connect[i]['name'] == c_name){ 
         connect[i]['appears'] += 1; 
         found = true; 
        } 
       } 
       if (found == false){ 
        var con = {'name':c_name,'appears':1}; 
        connect.push(con); 
       } 
       weight += 1; 
      };  
      emit(m_author, {'author':m_author, 'connections':connect, 'weight':weight}); 
     }; 
    } 

    function reducef(key, values) 
    { 
     var r = {'author':key, 'connections':[], 'weight':0}; 

     values.forEach(function(v) 
     { 
      for (c in v['connections']){ 
       c_name = v['connections'][c]['name']; 
       found = false; 
       for (i in r['connections']){ 
        if (r['connections'][i]['name'] == c_name){ 
         r['connections'][i]['appears'] += 1; 
         found = true; 
        } 
       } 
       if (found == false){ 
        var con = {'name':c_name,'appears':1}; 
        r['connections'].push(con); 
       } 
      }; 
      r.weight += v.weight; 
     }); 
     return r; 
    } 

這就導致所需類型的記錄:

{ 
    "_id" : "Skaundee", 
    "value" : { 
      "author" : "Skaundee", 
      "connections" : [ 
        { 
          "name" : "Carnage", 
          "appears" : 1 
        }, 
        { 
          "name" : "Tree", 
          "appears" : 1 
        } 
      ], 
      "weight" : 2 
    } 
} 
0

我認爲這個問題是你沒有定義connections如要定義它作爲一個元素mapper-的數組。關閉我的頭頂,看起來它應該閱讀:

var connect = [{'name':c['author'], 'appears':1}]; 
emit(m_author, {'author':m_author, 'connections':connect}); 
+0

將[]放在表示它變成一個數組而不是一個直線對象。不幸的是,這也意味着第一個條目(示例中的DarkKnight)從結果中消失。 – lanagj

+0

請記住,在Mongo中,reducer需要是transitive的 - 他們必須接受他們自己的輸出作爲輸入。 'c_name = v ['connections']。name;'如果輸入來自映射器則有效,但如果輸入來自另一個reducer則不適用。除上述更改外,您還需要更改其工作方式以包含其他forEach呼叫。見http://www.mongodb.org/display/DOCS/MapReduce#MapReduce-ReduceFunction –

+0

謝謝,我會繼續尋找併發布結果,當我_hopefully_有一個。 – lanagj