2010-07-15 5 views
4

Je suis assez nouveau pour CouchDB et j'ai encore quelques problèmes envelopper ma tête autour de toute façon MapReduce de mes données ... l'interrogationCount documents liés à CouchDB

rester avec l'exemple traditionnel « Blog », disons que j'ai 2 types de documents: post et comment ... chaque document de commentaire a un champ post_id ...

y at-il une manière que je peux obtenir une liste des postes avec le nombre de commentaires pour chacun de ces postes avec seulement 1 requête? Disons que je veux afficher la liste des titres de poste avec le nombre de commentaires pour chaque poste comme celui-ci:

My First Post: 4 comments 
My Second Post: 6 comments 
.... 

Je sais que je peux faire ce qui suit:

function(doc) { 
    if(doc.type == "comment") { 
     emit(doc.post_id, 1); 
    } 
} 

puis le réduire comme celui-ci :

function (key, values, rereduce) { 
    return sum(values); 
} 

qui me donne une liste de chaque billet de blog id, avec le nombre de commentaires pour chaque poste. Mais alors j'ai besoin de récupérer les titres des articles de blog séparément car la seule chose que j'ai en ce moment est leur identifiant ...

Alors, y a-t-il un moyen de retrouver une liste de chaque article de blog, avec le nombre de commentaires pour chaque poste, en faisant seulement 1 requête?

Répondre

0

Mon expérience est que dans la plupart des cas « normaux », vous êtes mieux d'avoir un gros document contenant à la fois le poste et les commentaires.

Bien sûr, je sais que ce n'est pas une bonne idée si vous avez des milliers de commentaires. C'est pourquoi j'ai dit "la plupart des cas normaux". Ne pas jeter cette option tout de suite, comme "impropre".

Vous obtenez toutes sortes de goodies comme pouvoir compter les commentaires comptent dans la vue de la carte, facile (une demande) récupération de la page entière de la base de données, ACID par courrier (avec commentaires) etc. Je n'ai pas besoin de penser à des tromperies comme la collation de vues en ce moment.

Si cela devient lent, vous pouvez toujours transformer votre structure de données plus tard (nous le faisions tous les jours avec RDBMS).

Si votre cas d'utilisation n'est pas totalement inadapté, je vous conseille vraiment de l'essayer. Cela fonctionne remarquablement bien.

+0

Je pense que le principal inconvénient à considérer ici serait des mises à jour plus lentes car vous devez aller chercher le document volumineux, ajouter le commentaire et renvoyer tout le contenu, puis vérifier les conflits et éventuellement recommencer s'il y en a. –

0

Vous pouvez faire quelque chose comme ceci:

function(doc) { 
    if(doc.type == "post") { 
     emit([doc._id, 'title', doc.title], 0); 
    } 
    if(doc.type == "comment") { 
     emit([doc.post_id, 'comments'], 1); 
    } 
} 

Ensuite, vous obtiendrez une vue où chaque poste reçoit deux lignes, l'une avec le titre et l'un des commentaires.

Vous pouvez fusionner les lignes ensemble sur le client, ou vous pouvez utiliser une fonction « liste » pour fusionner ces groupes de lignes ensemble dans CouchDB:

http://wiki.apache.org/couchdb/Formatting_with_Show_and_List

function list(head, req) { 
    var post; 
    var row; 
    var outputRow = function() { 
    if(post) { send(post); } 
    } 
    while(row = getRow()) { 
    if(!post || row.key[0] != post.id) { 
     outputRow(); 
     post = {id:row.key[0]}; 
    } 
    /* If key is a triple, use part 3 as the value, otherwise assume its a count */ 
    var value = row.key.length === 3 ? row.key[2] : row.value; 
    post[row.key[1]] = value; 
    } 
    outputRow(); 
} 

Note: le code non testé !