Najlepszy sposób, aby zrobić jeden do wielu "przyłączyć się" w CouchDB
Szukam CouchDB odpowiednik "SQL joins".
W moim przykładzie są dokumenty CouchDB, które są elementami listy:
{ "type" : "el", "id" : "1", "content" : "first" }
{ "type" : "el", "id" : "2", "content" : "second" }
{ "type" : "el", "id" : "3", "content" : "third" }
Istnieje jeden dokument, który definiuje listę:
{ "type" : "list", "elements" : ["2","1"] , "id" : "abc123" }
Jak widać trzeci element został usunięty, nie jest już częścią listy. Więc nie może być częścią wyniku. Teraz chcę widok, który zwraca elementy zawartości, w tym odpowiedniej kolejności.
Wynik może być:
{ "content" : ["second", "first"] }
W tym przypadku kolejność elementy są już takie, jakie powinny być. Inny możliwy wynik:
{ "content" : [{"content" : "first", "order" : 2},{"content" : "second", "order" : 1}] }
Zacząłem pisać funkcję mapy:
map = function (doc) {
if (doc.type === 'el') {
emit(doc.id, {"content" : doc.content}); //emit the id and the content
exit;
}
if (doc.type === 'list') {
for ( var i=0, l=doc.elements.length; i<l; ++i ){
emit(doc.elements[i], { "order" : i }); //emit the id and the order
}
}
}
Tylko tyle mogę osiągnąć. Czy możesz poprawić moje błędy i napisać funkcję redukcji? Pamiętaj, że trzeci dokument nie może być częścią wyniku.
Oczywiście można też napisać inną funkcję mapy. Nie można jednak zmienić struktury dokumentów (jednego dokumentu definig element i dokumentu wpisowego dla każdego wpisu).
Edytuj: Nie przegap komentarza JasonSmith ' a do jego odpowiedzi, gdzie opisuje, jak to zrobić krócej.
1 answers
Dziękuję! Jest to świetny przykład, aby pokazać nowy CouchDB 0.11 funkcje !
Musisz użyć funkcji fetch-related-data do dokumentów referencyjnych
w widoku. Opcjonalnie, dla wygodniejszego JSON, użyj funkcji _list
, aby
oczyść wyniki. W 2005 roku został wybrany do Izby Gmin.
Oto plan:
-
Po pierwsze, masz wyjątkowość contstraint na swoich
el
dokumentach. Jeśli dwa z mają id=2, to jest problem. Konieczne jest użycie pole_id
zamiast ifid
. CouchDB zagwarantuje wyjątkowość, ale także, reszta tego planu wymaga_id
, aby pobrać dokumenty według identyfikatora.{ "type" : "el", "_id" : "1", "content" : "first" } { "type" : "el", "_id" : "2", "content" : "second" } { "type" : "el", "_id" : "3", "content" : "third" }
Jeśli zmiana dokumentów na {[8] } jest absolutnie niemożliwa, możesz Utwórz prosty widok
emit(doc.id, doc)
, a następnie ponownie włóż go do tymczasowa baza danych. To konwertujeid
na_id
, ale dodaje trochę złożoności. -
Widok emituje {[15] } dane z kluczem
[list_id, sort_number]
, do "clump" listy z ich treścią.function(doc) { if(doc.type == 'list') { for (var i in doc.elements) { // Link to the el document's id. var id = doc.elements[i]; emit([doc.id, i], {'_id': id}); } } }
Teraz jest prosta lista
el
dokumentów, w odpowiedniej kolejności. Możesz użyjstartkey
iendkey
, jeśli chcesz zobaczyć tylko określoną listę.curl localhost:5984/x/_design/myapp/_view/els {"total_rows":2,"offset":0,"rows":[ {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"}}, {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"}} ]}
-
Aby uzyskać zawartość
el
, zapytanie zinclude_docs=true
. Through the magic of_id
,el
dokumenty zostaną załadowane.curl localhost:5984/x/_design/myapp/_view/els?include_docs=true {"total_rows":2,"offset":0,"rows":[ {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"},"doc":{"_id":"2","_rev":"1-4530dc6946d78f1e97f56568de5a85d9","type":"el","content":"second"}}, {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"},"doc":{"_id":"1","_rev":"1-852badd683f22ad4705ed9fcdea5b814","type":"el","content":"first"}} ]}
Uwaga, to już wszystkie potrzebne informacje. Jeśli twój Klient jest elastyczny, możesz analizować informacje z tego JSON. Następny opcjonalnie krok po prostu sformatuje go, aby pasował do tego, czego potrzebujesz.
-
Użyj funkcji
_list
, która po prostu sformatuje wyjście widoku. Ludzie używają ich do wyjścia XML lub HTML jednak zrobimy JSON wygodniejszy.function(head, req) { var headers = {'Content-Type': 'application/json'}; var result; if(req.query.include_docs != 'true') { start({'code': 400, headers: headers}); result = {'error': 'I require include_docs=true'}; } else { start({'headers': headers}); result = {'content': []}; while(row = getRow()) { result.content.push(row.doc.content); } } send(JSON.stringify(result)); }
Wyniki pasują. Oczywiście w produkcji będziesz potrzebował
startkey
iendkey
, aby określić listę, którą chcesz.curl -g 'localhost:5984/x/_design/myapp/_list/pretty/els?include_docs=true&startkey=["abc123",""]&endkey=["abc123",{}]' {"content":["second","first"]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:31