2010-06-13 23 views
32

"SQL birleştirmeleri" için CouchDB eşdeğeri arıyorum.CouchDB'de bire-çok "JOIN" yapmanın en iyi yolu

{ "type" : "el", "id" : "1", "content" : "first" } 
{ "type" : "el", "id" : "2", "content" : "second" } 
{ "type" : "el", "id" : "3", "content" : "third" } 

listesini tanımlar bir belge yoktur: Benim örnekte

liste unsurlardır CouchDB belgeleri bulunmaktadır

{ "type" : "list", "elements" : ["2","1"] , "id" : "abc123" } 

üçüncü unsur, onu silindi görebileceğiniz gibi artık listenin bir parçası değil. Yani sonucun bir parçası olmamalı. Şimdi, doğru sipariş dahil olmak üzere içerik öğelerini döndüren bir görünüm istiyorum.

sonucu olabilir: olması gerektiği gibi öğelerin sırası zaten bu durumda

{ "content" : ["second", "first"] } 

. Bir diğer olası sonucu:

{ "content" : [{"content" : "first", "order" : 2},{"content" : "second", "order" : 1}] } 

Ben haritası işlevini yazmaya başladı: Ancak bu kadar alabilirsiniz gibidir

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

. Hatalarımı düzeltebilir ve bir azaltma işlevi yazabilir misin? Üçüncü belgenin sonucun bir parçası olmaması gerektiğini unutmayın.

Elbette farklı bir harita işlevi de yazabilirsiniz. Ancak belgelerin yapısı (bir tanım elemanı ve her bir giriş için bir giriş belgesi) değiştirilemez.


DÜZENLEME: o bu kısa nasıl yapılacağı anlatılmaktadır Onun cevabını, hiç JasonSmith yorumuna kaçırmayın.

cevap

50

Teşekkür ederiz! Bu, CouchDB 0.11's new features'u göstermek için harika bir örnektir!

görünümünde, belgelerine başvuruda bulunmak için getirme ile ilgili veri özelliğini kullanmalısınız. İsteğe bağlı olarak, daha uygun JSON için sonuçları temizlemek için _list işlevini kullanın. Detaylar için bakınız Couchio's writeup on "JOIN"s.

  1. Öncelikle, sizin el belgeler üzerinde bir benzersizliği contstraint vardır: İşte

    planıdır. 'dan ikisi id = 2'ye sahipse, bu bir problemdir. id yerine _id alanını kullanmak gereklidir. CouchDB, benzersizliği garanti edecektir, ancak , bu planın geri kalanı kimliklerini kimliğe göre almak için _id gerektirir. belgeleri değişen _id kesinlikle imkansızdır kullanmak durumunda
    { "type" : "el", "_id" : "1", "content" : "first" } 
    { "type" : "el", "_id" : "2", "content" : "second" } 
    { "type" : "el", "_id" : "3", "content" : "third" } 
    

    , sen bir geçici veritabanına o takın sonra yeniden emit(doc.id, doc) için basit bir görünüm oluşturabilir ve. Bu, id'u _id'a dönüştürür, ancak biraz karmaşıklık ekler.

  2. görünümü içerikleriyle [list_id, sort_number] üzerine kademeli {"_id": content_id} verileri için "kümeleşme" listeleri yayar.

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

    Şimdi doğru sırayla el belgelerin basit liste vardır. Sadece belirli bir listeyi görmek isterseniz startkey ve endkey numaralarını kullanabilirsiniz.

    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. include_docs=true ile el içerik, sorguyu almak için. _id'un büyüsüyle el belgeleri yüklenir.

    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"}} 
    ]} 
    

    Dikkat, bu zaten ihtiyacınız olan tüm bilgilerdir. İstemciniz esnek ise, bu JSON'dan bilgileri ayrıştırabilirsiniz. Sonraki isteğe bağlı adımı, ihtiyacınız olanı eşleştirmek için onu yeniden biçimlendirir.

  4. Görünüm çıktısını yeniden biçimlendiren bir _list işlevini kullanın. İnsanlar bunları XML veya HTML çıktıları için kullanır, ancak biz JSON'u daha kullanışlı hale getireceğiz. Sonuçlar eşleşir.

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

    Tabii ki üretimde, istediğiniz listeyi belirtmek için startkey ve endkey'a ihtiyacınız olacak.

    curl -g 'localhost:5984/x/_design/myapp/_list/pretty/els?include_docs=true&startkey=["abc123",""]&endkey=["abc123",{}]' 
    {"content":["second","first"]} 
    
+3

Kelime, bu kapsamlı bir tanesidir. İyi iş jhs! –

+2

Yanıltıcı şekilde uzun. Aslında adım # 2 tam bir çözüm, ancak evet, arka plan gereksinimleri ve istemci tarafında kolaylık eklemek için isteğe bağlı yollar ayrıntılı. – JasonSmith

+1

CouchIO URL değişti, burada aynı makale için yeni bir tane var: http://couchio.tumblr.com/post/446015664/whats-new-in-apache-couchdb-011-part-two – Bdoserror

İlgili konular