2010-03-16 57 views
2

我在尋找一個map/reduce函數來計算設計文檔中的狀態。 您可以在下面看到我當前數據庫中的示例文檔。在CouchDB中對散列數組進行映射/縮小

{ 
    "_id": "0238f1414f2f95a47266ca43709a6591", 
    "_rev": "22-24a741981b4de71f33cc70c7e5744442", 
    "status": "retrieved image urls", 
    "term": "Lucas Winter", 
    "urls": [ 
     { 
      "status": "retrieved", 
      "url": "http://...." 
     }, 
     { 
      "status": "retrieved", 
      "url": "http://..." 
     } 
    ], 
    "search_depth": 1, 
    "possible_labels": { 
     "gender": "male" 
    }, 
    "couchrest-type": "SearchTerm" 
} 

我想擺脫status關鍵的和而從URL的狀態計算。 我現在by_status圖如下所示:

function(doc) { 
    if (doc['status']) { 
     emit(doc['status'], null); 
    } 
} 

我嘗試了一些東西,但沒有任何實際工作。現在我Map Function看起來是這樣的:

function(doc) { 
    if(doc.urls){ 
     emit(doc._id, doc.urls) 
    } 
} 

而且我Reduce Function

function(key, value, rereduce){ 
    var reduced_status = "retrieved" 
    for(var url in value){ 
     if(url.status=="new"){ 
      reduced_status = "new"; 
     } 
    } 
    return reduced_status; 
} 

結果是我得到檢索到處是絕對不正確的。

我試圖縮小問題,它似乎是value是沒有數組,當我用下面的Reduce Function我得到的長度爲1無處不在,這是不可能的,因爲我有我的數據庫文件12,20之間的每個含200個網址

function(key, value, rereduce){ 
    return value.length; 
} 

alt text http://img.skitch.com/20100316-qeawxgd5pru8d5i6bprygcsmhf.jpg

我在做什麼錯? (我知道我希望你爲我編寫代碼,我感到內疚,但是現在我從數據庫中獲取數據之後計算ruby中的狀態。如果已經從數據庫獲取了正確的數據數據庫)

+0

什麼JSON.stringify(value)返回? (JSON是Firefox 3.5+中的本地窗口對象) – Alsciende 2010-03-16 13:20:01

回答

3

reduce函數的變量value是由map函數發出的值的數組。在你的情況下,value是由「url」陣列組成的數組。在蒲團中運行map-reduce時,它將設置group=true,以便map-reduce對於map函數發出的每個鍵單獨運行。在你的情況下,這些密鑰是文件_ids。也就是說,reduce函數的value是一個數組,其元素都是屬於某個doc _id的url數組。由於doc _id是獨一無二的,因此最終減法函數的value是一個包含一個元素的數組,此元素是相應文檔的url數組。這就是爲什麼value.length總是與您的減少功能1。

但它可能會變得更糟:如果最終進入rereduce循環,reduce函數的value是由先前調用reduce函數返回的值數組。在你的情況下,你可以調用reduce函數value看起來像["retrieved","new","retrieved"],這不會導致正確的結果。

通常,reduce函數用於聚合map-function發出的數據,例如計算行數或合計值 - 在您的情況下這不是必需的。你可以閱讀更多CouchDB中有關的map-reduce這裏:

http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views

http://books.couchdb.org/relax/design-documents/views

1

doc.urls似乎是包含status屬性和url屬性的Object的數組。所以,你的Reduce函數應該是這樣

function(key, value, rereduce){ 
    var reduced_status = "retrieved"; 
    for(var i=0; i<value.length; i++) { 
     if(value[i].status=="new"){ 
      reduced_status = "new"; 
     } 
    } 
    return reduced_status; 
} 

編輯:實際上它找到status == "new"功能應該很快就會回來。

+0

唯一的問題是,value.length始終爲1 - 請參閱原始問題的下半部分 - 我不知道爲什麼,因爲doc.urls應該包含20和200個散列。 – sebastiangeiger 2010-03-16 12:51:41

+0

好的,但仍然,你的Reduce功能是非常錯誤的。 For..in並不像你認爲它的工作方式那樣工作。 – Alsciende 2010-03-16 13:17:38

0

謝謝Alsciende推動我走向正確的解決方案,事實證明我真的不明白減少功能。我根本不需要減少功能。

這是我的Map Function,它爲我解決它。

function(doc) { 
if(doc.urls){ 
    var reduced_status = "retrieved"; 
    for(var i=0; i<doc.urls.length; i++) { 
    if(doc.urls[i].status=="new"){ 
     reduced_status = "new"; 
     break; 
    } 
    } 
    emit(reduced_status, null); 
    } 
}