La meilleure façon de faire un à plusieurs "joindre" dans CouchDB
je cherche un CouchDB équivalent à"SQL joins".
dans mon exemple il y a des documents CouchDB qui sont des éléments de liste:
{ "type" : "el", "id" : "1", "content" : "first" }
{ "type" : "el", "id" : "2", "content" : "second" }
{ "type" : "el", "id" : "3", "content" : "third" }
il y a un document qui définit la liste:
{ "type" : "list", "elements" : ["2","1"] , "id" : "abc123" }
Comme vous pouvez le voir le troisième élément a été supprimé, il ne fait plus partie de la liste. Cela ne doit donc pas faire partie du résultat. Maintenant je veux une vue qui renvoie les éléments de contenu incluant le bon ordre.
le résultat pourrait être:
{ "content" : ["second", "first"] }
Dans ce cas, l'ordre des éléments est déjà comme il se doit. Un autre résultat possible:
{ "content" : [{"content" : "first", "order" : 2},{"content" : "second", "order" : 1}] }
j'ai commencé à écrire la fonction de carte:
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
}
}
}
Je ne peux pas aller plus loin. Pouvez-vous corriger mes erreurs et d'écrire une fonction de réduction? Rappelez-vous que le troisième document ne doit pas faire partie du résultat.
bien sûr que vous pouvez écrivez une fonction de carte différente aussi. Mais la structure des documents (un élément de définition et un document d'entrée pour chaque entrée) ne peut pas être modifiée.
EDIT: Ne manquez pas JasonSmith commentaire de sa réponse, où il décrit comment faire plus court.
1 réponses
Merci! C'est un bon exemple pour montrer la nouvelle version de CouchDB 0.11 de les fonctionnalités !
Vous devez utiliser le fetch-option de données, de documents de référence
dans la vue. en option, pour plus de commodité, JSON, l'utilisation d'un _list
la fonction de
nettoyer les résultats. Pour plus de détails, voir couchio's writeup sur "JOIN"s .
voici le plan:
-
tout d'abord, vous avez un contenu unique sur vos documents
el
. Si deux de ils ont id=2, c'est un problème. Il est nécessaire d'utiliser le champ_id
à la place deid
. CouchDB garantira l'unicité, mais aussi, le reste de ce plan nécessite_id
pour aller chercher des documents par carte D'identité.{ "type" : "el", "_id" : "1", "content" : "first" } { "type" : "el", "_id" : "2", "content" : "second" } { "type" : "el", "_id" : "3", "content" : "third" }
si changer les documents pour utiliser
_id
est absolument impossible, vous pouvez créer une vue simple pouremit(doc.id, doc)
et ensuite réinsérer cela dans un base de données temporaire. Cela convertitid
en_id
mais ajoute une certaine complexité. -
Le point de vue émet
{"_id": content_id}
données saisies sur[list_id, sort_number]
, de "touffe" les listes avec leur contenu.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}); } } }
maintenant il y a une simple liste de documents
el
, dans le bon ordre. Vous pouvez utiliserstartkey
etendkey
si vous voulez voir seulement un particulier liste.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"}} ]}
-
pour obtenir le contenu
el
, interrogez avecinclude_docs=true
. Grâce à la magie de_id
, les documentsel
se chargeront.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"}} ]}
avis, c'est déjà toutes les informations dont vous avez besoin. Si votre client est flexible, vous pouvez extraire l'information de ce JSON. Le suivant optionnel step le reformate simplement pour correspondre à ce dont vous avez besoin.
-
utilisez une fonction
_list
, qui reformate simplement la sortie de vue. Les gens les utilisent pour produire XML ou HTML cependant nous ferons le JSON est plus pratique.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)); }
les résultats correspondent. Bien sûr, dans la production, vous aurez besoin de
startkey
etendkey
pour spécifier la liste que vous souhaitez.curl -g 'localhost:5984/x/_design/myapp/_list/pretty/els?include_docs=true&startkey=["abc123",""]&endkey=["abc123",{}]' {"content":["second","first"]}