2014-06-09 46 views
1

我處理文件,如以下各項之一:MapReduce的分割輸入串入輸出數組

> db.productData.find({"upc" : "XXX"}).pretty() 
{ 
    "_id" : ObjectId("538dfa3d44e19b2bcf590a77"), 
    "upc" : "XXX", 
    "productDescription" : "bla foo bar bla bla fooX barY", 
    "productSize" : "", 
    "ingredients" : "foo; bar; foo1; bar1.", 
    "notes" : "bla bla bla" 
} 
> 
  • 我想有含有的字段,列表/分裂成分的陣列中的文件(在;)。我想將原始集合的字符串拆分爲一個字符串數組。
  • 我想只映射輸出集合中的一些輸入字段。
  • 我想在MongoDB上使用mapreduce

我已經嘗試了很多不同的方式從map功能移動的東西到reduce功能未能找到一個妥善的解決辦法。 從我所進行的嘗試,現在我知道我需要檢查null值等,所以下面一個是我最後一次嘗試:

地圖功能:

var mapperProductData = function() { 

    var ingredientsSplitted = values.ingredientsString.split(';'); 

    var objToEmit = {barcode : "", description : "", ingredients : []}; 

    // checking for null (is this strictly necessary? why?) 
    if ( 
      this.hasOwnProperty('ingredients') 
     && this.hasOwnProperty('productDescription') 
     && this.hasOwnProperty('upc') 
     ) { 
     for (var i = 0; i < ingredientsSplitted.length; i++) { 
      // I want to emit a new document only when I have all the splitted strings inside the array 
      if (i == ingredientsSplitted.length - 1) { 
       objToEmit.barcode  = this.upc; 
       objToEmit.description = this.productDescription; 
       objToEmit.ingredients = ingredientsSplitted; 

       emit(this.upc, objToEmit); 
      } 
     } 
    } 
}; 

的減少功能:

var reducerNewMongoCollection = function(key, values) { 

    return values; 
}; 

的地圖,減少電話:

db.productData.mapReduce(
    mapperProductData, 
    reducerNewMongoCollection, 
    { 
     out : "newMongoCollection" , 
     query: { "values" : {$exists: true} } 
    } 
); 

我在輸出中獲得一個空集合(newMongoCollection爲空)。 我在做什麼錯?

回答

3

讓我們從頭開始。你的地圖功能應該是這樣的:

var mapperProductData = function() {  
    var ingredientsSplitted = this.ingredients.split(';');  
    var objToEmit = { 
     barcode : this.upc, 
     description : this.productDescription, 
     ingredients : ingredientsSplitted 
    }; 

    emit(this.upc, objToEmit);   
}; 

你的map-reduce調用應該是:

db.productData.mapReduce(
    mapperProductData, 
    reducerNewMongoCollection, 
    { 
     out : "newMongoCollection", 
     query : { 
      upc : { $exists : true }, 
      productDescription : { $exists : true }, 
      ingredients : { $exists : true , $type : 4 } 
     } 
    } 
); 

的查詢部分將過濾那些具有相關領域的文件。另外,查詢參數$type將僅匹配其中成分是數組的文檔。這樣您就不需要在地圖功能中進行復雜的檢查,並且發送到map函數的文檔數量會更少。

您的測試文檔的文檔看起來就像這樣的結果:

key : XXX, 
value: { 
    "barcode" : "XXX", 
    "description" : "bla foo bar bla bla fooX barY", 
    "ingredients" : [ 
     "foo", 
     " bar", 
     " foo1", 
     " bar1." 
    ] 
}