2010-07-28 2 views
5

내 CouchDB 데이터베이스에 저장된 두 가지 유형의 문서가 있다고 가정 해 보겠습니다. 첫 번째 속성 유형은 으로 설정하고 두 번째 값은 입니다. 연락처 유형 문서에는 name이라는 또 다른 속성이 있습니다. 전화 유형은 특성 번호 number 및 contact_id를 가지므로 담당자에게 참조 할 수 있습니다. 이것은 하나의 연락처가 N 개의 전화 번호를 가질 수있는 사소한 일대 다 시나리오입니다 (단일 연락처 문서에 임베드 될 수 있음을 알고 있지만 다른 문서와 많은 관계를 보여줄 필요가 있음). 스콧 2 개 전화 번호를 갖는 매트 한 번호를 갖는두 개의 분리 된 문서에서 임베디드 배열로 JSON 객체를 구성하는 CouchDB보기

원시 예 데이터 :

{_id: "fc93f785e6bd8c44f14468828b001109", _rev: "1-fdc8d121351b0f5c6d7e288399c7a5b6", type: "phone", number: "123456", contact_id: "fc93f785e6bd8c44f14468828b00099f"} 
{_id: "fc93f785e6bd8c44f14468828b000f6a", _rev: "1-b2dd90295693dc395019deec7cbf89c7", type: "phone", number: "465789", contact_id: "fc93f785e6bd8c44f14468828b00099f"} 
{_id: "fc93f785e6bd8c44f14468828b00099f", _rev: "1-bd643a6b0e90c997a42d8c04c5c06af6", type: "contact", name: "Scott"} 
{_id: "16309fcd03475b9a2924c61d690018e3", _rev: "1-723b7c999111b116c353a4fdab11ddc0", type: "contact", name: "Matt"} 
{_id: "16309fcd03475b9a2924c61d69000aef", _rev: "3-67193f1bfa8ed21c68e3d35847e9060a", type: "phone", number: "789456", contact_id: "16309fcd03475b9a2924c61d690018e3"} 

지도 기능 :

function(keys, values) { 
    var output = {}; 

    for(var elem in values) { 
    if(values[elem].type == "contact") { 
     output = { 
     "ID": values[elem]._id, 
     "Name": values[elem].name, 
     "Type": values[elem].type, 
     "Phones": [] 
     }; 
    } else if (values[elem].type == "phone") { 
     output.Phones.push({ 
     "Number": values[elem].number, 
     "Type": values[elem].type 
     }); 
    } 
    } 

    return output; 
} 

group_level로 설정된다

function(doc) { 
    if (doc.type == "contact") { 
    emit([doc._id, 1], doc); 
    } else if (doc.type == "phone") { 
    emit([doc.contact_id, 0], doc); 
    } 
} 

기능 줄이기 1 Map 기능의 키 때문입니다.

http://localhost:5984/testdb2/_design/testview/_view/tv1?group_level=1 

을 또는이 같은 startkey 및 endkey 일부 연락처를 검색 : 지금은이 같은 예를 들어 포함 휴대폰 내 연락처를 얻을 수

http://localhost:5984/testdb2/_design/testview/_view/tv1?group_level=1&startkey=[%22fc93f785e6bd8c44f14468828b00099f%22]&endkey=[%22fc93f785e6bd8c44f14468828b00099f%22,{}] 

결과는 정확히 내가 원하는 방법을 찾아 - 연락처해야합니다 임베디드 전화는 일대 다 관계에 따라. 여기 CouchDB에서 MapReduce 함수를 사용하는 올바른 방법인가? 이 접근법을 사용할 때 주목할만한 성능 문제가 있습니까?

답변

7

일반적으로 말해서 emit(...,doc)이 아닌 경우 디스크 공간을 덜 사용합니다.

감소 기능이있는 것을 다시 생각해 볼 수 있습니다. 필요한 데이터를 확보 할 필요가 없습니다. 예를 들어, 다음 행의 내용은 디스크 공간을 덜 사용하고 많은 수의 레코드가있는 경우 더 잘 수행 할 수 있습니다.

또한 CouchDB는 문서에 포함 된 것보다 더 많은 데이터를 축소 기능으로 작성하는 것에 반대한다고 생각합니다. 이 경우에는 그렇게하지 않지만 나중에 문제가 될 수있는 패턴을 따르고 있습니다. 그것은 이유를 위해 감소라고합니다. :-)

그래서 이런 일이 더 CouchDB를 방법입니다 :

http://localhost:5984/testdb2/_design/testview/_view/tv1? 
    startkey=[%22fc93f785e6bd8c44f14468828b00099f%22, 0] 
    &endkey=[%22fc93f785e6bd8c44f14468828b00099f%22,1] 

은 부여, 동일한 결과를 얻을하지 않습니다 그래서 같은 특정 연락처에 대한

function(doc) { 
    if (doc.type == "contact") { 
    emit([doc._id, 0], { 
     "Name": doc.name, 
     "Type": doc.type 
    }); 
    } else if (doc.type == "phone") { 
    emit([doc.contact_id, 1], { 
     "Number": doc.number, 
     "Type": doc.type 
    }); 
    } 
}

쿼리를 JSON 구조는 이전과 같지만 CouchDB 내에서 더 나은 성능을 보입니다.

0

이 답변은 완전히 외계와 일화이지만, CouchDB에서 일대 다 관계로 작업 한 것과 거의 같습니다. 스케일링 문제가 있다면 아직 보지 못했습니다. (그러나 나는 그들을 찾기에는 너무 열심히 노력하지 않았다는 것을 인정한다.)

지도 기능에서 왜 전화 번호가 연락처 (1) 앞에 먼저 오도록 정렬 되었습니까? reduce 함수에는 반대 순서가 필요합니다.

+0

브라우저에서 직접보기에 액세스 할 때 URL에 내림차순 = true를 삽입해야하므로 정렬됩니다. – yojimbo87