2010-07-28 8 views
5

Powiedzmy, że mam dwa typy dokumentów przechowywanych w mojej bazie danych CouchDB. Najpierw typ własności ustawiony na , kontakt i drugi numer telefon. Dokument typu kontaktu ma inną właściwość o nazwie nazwa. Typ telefonu ma numer właściwości i contact_id, aby mógł odnosić się do osoby kontaktowej. Jest to trywialne w przypadku wielu scenariuszy, w których jeden kontakt może mieć numery telefonów N (wiem, że mogą one być osadzone w jednym dokumencie kontaktowym, ale muszę wykazać jeden do wielu relacji z różnymi dokumentami).Widok CouchDB komponowanie obiektów JSON z osadzonymi tablicami z dwóch oddzielnych dokumentów

Raw przykładowe dane z Scott mając 2 numery telefonów i Matt mający 1 Numer:

{_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"} 

funkcja Map:

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 jest ustawiony na: funkcja

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

Zmniejszyć 1 ze względu na klawisze w funkcji mapy. Teraz mogę dostać moje kontakty z włączonych telefonów na przykład tak:

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

Albo poszukać jakiegoś kontaktu z startkey i endkey jak ten:

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

wyniki wyglądają dokładnie tak, jak chcę - kontakty będą mieć wbudowane telefony według jednego do wielu relacji. I tu pojawia się pytanie: czy jest to właściwy sposób korzystania z funkcji MapReduce w CouchDB? Czy są jakieś istotne problemy z wydajnością podczas korzystania z tego podejścia?

Odpowiedz

7

Ogólnie rzecz biorąc zużywa się mniej miejsca na dysku, jeśli nie jest to emit(...,doc).

Być może zechcesz w ogóle rozważyć zastosowanie funkcji redukcji. Naprawdę nie jest konieczne uzyskiwanie potrzebnych danych. Na przykład coś podobnego do poniższego może zużywać mniej miejsca na dysku i działać lepiej, jeśli masz ogromną liczbę rekordów.

Uważam również, że jest to sprzeczne z CouchDB, aby gromadzić więcej danych w funkcji redukcji niż zawarte w dokumentach. W tym przypadku nie robisz tego, ale postępujesz zgodnie ze wzorcem, który może później popaść w kłopoty. Z jakiegoś powodu nazywa się to zmniejszeniem. :-)

Więc coś w tym jest bardziej sposobem CouchDB:

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

Zapytanie go do konkretnego kontaktu tak:

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

prawda, nie dostaniesz wyniki w tym samym Struktura JSON jak poprzednio, ale wierzę, że to działa lepiej w CouchDB.

0

Ta odpowiedź jest całkowicie apokryficzna i anegdotyczna, ale to dokładnie tak, jak pracowałem z relacjami jeden-do-wielu w CouchDB. Jeśli są jakieś problemy z skalowaniem, nie widziałem ich jeszcze. (Przyznaję jednak, że nie próbowałem ich zbyt wiele).

Mimo, że w twojej funkcji mapy, dlaczego masz telefon posortowany, aby wyjść pierwszy (0) przed kontaktem (1)? Twoja funkcja redukcji wymaga przeciwnej kolejności.

+0

To jest tak posortowane, ponieważ kiedy wchodzę do widoku bezpośrednio przez przeglądarkę, będę musiał wstawić malejąco do adresu URL. – yojimbo87

Powiązane problemy