2010-03-22 10 views
1

Ma base de données CouchDB comme principal type de document qui ressemble à:Comment puis-je voir les documents utilisateur favoris par utilisateur dans Couchdb map/reduce?

{ 
    "_id" : "doc1", 
    "type" : "main_doc", 
    "title" : "the first doc" 
    ... 
} 

Il y a un autre type de document qui stocke des informations utilisateur. Je souhaite que les utilisateurs puissent étiqueter les documents en tant que favoris. Différents utilisateurs peuvent enregistrer des documents identiques ou différents en tant que favoris. Mon idée était de présenter un document favori pour suivre ce quelque chose comme:

{ 
    "_id" : "fav1", 
    "type" : "favorite", 
    "user_id" : "user1", 
    "doc_id" : "doc1" 
} 

Il est assez facile de créer une vue avec user_id comme la clé pour obtenir une liste de leurs identifiants de documents préférés. Par exemple:

function(doc) { 
    if (doc.type == "favorite") { 
     emit(doc.user_id, doc.doc_id); 
    } 
} 

Cependant, je veux la liste des favoris pour afficher la user_id, doc_id et le titre du document. quelque chose comme sortie Donc:

{ "key" : "user1", "value" : ["doc1", "the first doc"] } 
+0

Ou est-ce que ce ne serait vraiment pas trop cher d'aller chercher les titres de document dans des requêtes séparées? J'ai déjà une autre vue qui produit l'ID du document et le titre. J'essayais d'éviter d'exiger un autre appel à la DB pour obtenir le titre du document pour chaque favori. –

Répondre

2

Dans CouchDB 0.11 (tout récemment sorti), la fonction include_docs=trueallows you to look up any document in your view row. Par exemple:

function(doc) { 
    if(doc.type == "favorite") { 
     emit(doc.user_id, {_id: doc.doc_id}); 
    } 
} 

Lorsque vous interrogez votre point de vue avec include_docs=true, vous devriez voir JSON comme ceci:

// ... normal stuff 
rows: [ 
    { 
    "key":"user1", 
    "value":{"_id":"doc1"}, 
    "doc": { 
     "_id" : "doc1", 
     "type" : "main_doc", 
     "title" : "the first doc" 
     // ... 
    } 
    }, 
    { 
    // another doc, etc... 
    } 
] 
+0

Ceci est une nouvelle fonctionnalité intéressante, mais je ne veux pas retourner le document entier. Je veux juste une liste d'articles préférés avec le titre seulement. J'ai seulement besoin du document entier si un utilisateur sélectionne pour regarder un document. –

+0

Oui, je comprends. Aussi ma solution vous forcerait à mettre à jour bien sûr. Mais je ne sais pas comment vous pouvez accomplir ce que vous voulez sans un refactor "schéma". – JasonSmith

+0

Je considérerais refactoring comment les docs sont disposés pour adapter ceci. Aucune suggestion? –

0

Si vous ne pouvez pas utiliser la fonction include_docs=true avec v0.11, alors vous devez avoir toutes les informations à portée de main lorsque vous émettez des données pour votre vue/carte. Au lieu d'un style "join" traditionnel, pensez à stocker une liste d'utilisateurs "favorisants" dans les documents main_doc. Ainsi, lorsque votre vue s'exécute, vous pouvez tout émettre en fonction des informations contenues dans ce document.

function(doc) { 
    if(doc.type == "main_doc") { 
     for (var a in doc.favorited_by) { 
      emit(doc.favorited_by[a], [doc._id, doc.title]); 
     } 
    } 
} 
+0

Ne pourrais-je pas rencontrer des problèmes d'évolutivité ici? Si beaucoup d'utilisateurs essaient d'ajouter ce même document en tant que favori, je risque de rencontrer beaucoup de conflits. –

+0

Oui, vous avez raison. C'est un compromis qui dépend de votre utilisation prévue. Une autre idée est de le stocker dans l'autre sens: stocker '[" doc_id "," Doc Title "]' tuples dans l'objet utilisateur. Cela nécessiterait trois allers-retours (1: aller chercher le principal doc; 2: chercher le doc de l'utilisateur, 3: mettre à jour le doc de l'utilisateur avec la nouvelle tuple) mais vous pourriez avoir déjà tous ces documents à portée de main au moment nécessaire. Je préférerais encore cela par rapport à plusieurs recherches au moment de la lecture via vos documents de style de jointure. – JasonSmith

+0

J'espérais une seule opération de lecture sur les recherches favorites.J'essayais aussi d'éviter de copier le titre du document dans d'autres docs, car si le titre est mis à jour dans le document, le titre copié est obsolète ou je dois trouver et mettre à jour tous les documents utilisateur avec ce document comme favori. –