2010-03-16 5 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; 
} 

결과를 확실히 바로하지 않은 모든 곳에서 검색 얻을 것입니다.

나는 문제를 좁히려고했는데 다음을 사용할 때 이 배열이 아닌 것 같다. Reduce Function 내 데이터베이스에 12 개의 문서가 있기 때문에 어느 곳에서나 길이 1을 얻을 수 없다. 200 개 URL을

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

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

에 내가 잘못 뭐하는 거지? (나는 당신이 나를 위해 코드를 작성하고 죄책감을 느낀다는 것을 알고 있지만, 지금은 데이터베이스에서 데이터를 가져온 후에 루비에서 상태의 계산을 수행한다. 이미 올바른 데이터를 얻는 것이 좋을 것이다. 데이터베이스)

+0

무엇 JSON.stringify (값)을 반환합니까? (JSON은 파이어 폭스 3.5 이상의 네이티브 윈도우 객체입니다.) – Alsciende

답변

3

reduce 함수의 변수 value은 맵 함수가 내 보낸 값 배열입니다. 귀하의 경우 value은 "url"배열로 구성된 배열입니다. futon에서 map-reduce를 실행할 때 map-reduce가 map 함수에서 방출 된 모든 키에 대해 별도로 실행되도록 group=true을 설정합니다. 귀하의 경우, 이러한 키는 _ids 문서입니다. 즉, reduce 함수의 value은 요소가 특정 doc _id에 속한 모든 url-array 인 배열입니다. doc _ids는 고유하므로 reduce 함수의 value이 하나의 요소가있는 배열이되므로이 요소는 해당 doc의 url 배열입니다. 따라서 value.length은 항상 reduce 함수를 사용하여 1입니다.

하지만 악화 될 수 있습니다. rereduce-cycle으로 끝나는 경우 reduce 함수의 value은 이전 reduce 함수 호출에서 반환 된 값 배열입니다. 귀하의 경우 value과 같은 reduce 함수를 ["retrieved","new","retrieved"]과 같이 호출하면 올바른 결과가 나오지 않습니다.

일반적으로 reduce 함수는 map 함수가 내 보낸 데이터를 집계하는 데 사용됩니다. 예를 들어 행을 계산하거나 합계 값을 계산하는 경우가 있습니다.이 경우에는 필요하지 않습니다. 여기 CouchDB를에지도-감소에 대한 자세한 내용을보실 수 있습니다 :

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

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

1

doc.urlsstatus 속성과 url 속성을 포함하는 Object의 배열 인 것으로 보입니다. 이 status == "new"를 발견로 실제로 함수가 즉시 반환해야합니다 : 그래서 당신의 감소 기능은

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; 
} 

편집과 같이해야한다.

+0

유일하게 문제는, value.length는 항상 1입니다. - 원래 질문의 하위 3 분의 1을 봅니다. 왜 그런지 모르겠지만, doc.urls에는 20 및 200 해시. – sebastiangeiger

+0

그래도 그래도 Reduce 기능이 매우 잘못되었습니다. For..in은 작동한다고 생각하는 것처럼 작동하지 않습니다. – Alsciende

0

알맞은 솔루션으로 나를 밀어 주셔서 감사합니다 Alsciende, 나는 정말로 감소 기능을 이해하지 못했던 것으로 밝혀졌습니다. 나는 reduce 함수를 전혀 필요로하지 않았다.

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); 
    } 
} 
관련 문제