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.

Author: mit, 2010-06-13

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:

  1. 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 if id. 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 konwertuje id na _id, ale dodaje trochę złożoności.

  2. 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żyj startkey i endkey, 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"}}
    ]}
    
  3. Aby uzyskać zawartość el, zapytanie z include_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.

  4. 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 i endkey, 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"]}
    
 50
Author: JasonSmith,
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