2010-12-13 53 views
1

Ceci est ma première question ici sur stackoverflow, donc j'espère que je suis le protocole correct.Puis-je commander des documents CouchDB par clé commune?

Je crée un jeu de base basé sur CouchDB et NodeJS. Dans mon jeu, les utilisateurs peuvent avoir plusieurs caractères. J'ai décidé de séparer les joueurs de leurs personnages dans la base de données parce que j'ai rarement besoin d'associer des données de compte utilisateur (email, vrai nom, etc) avec leurs données de personnage. De toute façon, voici mon problème:

Je veux être capable de créer une vue qui retourne tous les caractères qui sont contrôlés par un joueur. Il y aura une propriété appelée "propriétaire" dans ce document. Je pense que la façon la plus simple de faire ceci est de faire une vue qui retourne une liste de tous les caractères catégorisés par le propriétaire.

Voici mon code à ce jour:

fonction

(doc) { Emit (doc.owner, doc); }

J'essaie d'obtenir un tel résultat (note, ceci est simplifié, je sais CouchDB inclut d'autres données dans la sortie):

{ 
    "player1":{ 
     "character1":{ 
      "data":{} 
     }, 
     "character2":{ 
      "data":{} 
     } 
    }, 
    "player2":{ 
     "character1":{ 
      "data":{} 
     }, 
     "character2":{ 
      "data":{} 
     } 
    } 
} 

Avez-clés doivent être uniques? Mon code me donnera-t-il le résultat souhaité? Je ne suis pas marié à l'idée de séparer les données, et je pourrais aussi simplement mettre les caractères sous le document utilisateur et créer deux vues, une qui n'émettrait que les données du compte utilisateur et omettre les données de caractères et un autre pour émettre seulement les données de caractères et omettre les données de l'utilisateur, mais cela me semble un peu gênant. Je préfère garder les données séparées car il se peut que je doive écrire d'autres vues spécifiques aux données de personnage, et il semble que ce serait mieux organisé si je séparais les personnages des lecteurs de la base de données. Sur une note connexe, y a-t-il un moyen de filtrer les réponses en passant un second paramètre? Je suppose que cela nie l'efficacité d'une vue et que je devrais probablement utiliser une vue temporaire dans ce cas. Mon problème avec cela est que je pourrais potentiellement avoir une grande quantité de données retournées par cette vue (la base de données entière en fait), ce qui pourrait être très lent lors du transfert sur HTTP, d'autant plus que je n'aurai pas besoin de la plupart des données.

Une autre solution possible consiste à stocker le _id de chaque caractère qu'un utilisateur contrôle en tant que propriété dans la base de données du compte utilisateur. Cela me semble assez sensé, mais s'il y a une option différente, ou oserais-je dire «meilleure», alors j'aimerais l'entendre.

Quelle serait la meilleure solution à ce problème?

Merci beaucoup d'avance pour votre aide.

+0

wow, votre première question et maintenant vous êtes 10k + :) ... – TimoSolo

Répondre

4

Vous êtes sur la bonne voie. Si vous souhaitez faire une réduction, vous pouvez définir cette carte:

function(doc) { 
    var r = {}, c = {}; 
    c[doc._id] = doc; 
    r[doc.owner] = c; 
    emit(doc.owner,r); 
} 

Et cela réduit:

function(k,v,red) { 
    var r = {}; 
    for (var i in v) { 
    for (var owner in v[i]) { 
     if (!(owner in r)) r[owner] = {}; 
     for (var character in v[i][owner]) 
     r[owner][character] = v[i][owner][character]; 
    } 
    } 
    return r; 
} 

Cela devrait revenir directement ce que vous avez demandé, mais est à peine optimale: la vue doit stocker beaucoup de données pour les parties Carte et Réduire ...

Au lieu de cela, je pencherais pour une carte sans réduire, comme ceci:

function(doc) { 
    emit(doc.owner,null); 
} 

Cette carte, lorsqu'il est interrogé avec include_docs=true, renverrait des lignes qui ressemblent à ceci:

[ 
    { id : 'charid', key : 'playid', doc : { /* character document */ } }, 
    ... 
] 

Le serveur la charge est plus légère, et vous pouvez toujours regrouper les personnages par joueur en utilisant le key dans le résultat, si vous en avez vraiment besoin. Les résultats sont triés par key, puis par id.

Vous pouvez interroger cette vue en utilisant startkey et endkey tous les deux égaux à l'identifiant du joueur pour obtenir tous les caractères d'un joueur. Si vous avez seulement besoin des identifiants de caractères, ajoutez include_docs=false et la partie lourde doc ne sera pas envoyée.

+0

Je pense que je vais créer un design de doc pour les deux solutions et essayer les deux pour voir ce que j'aime mieux. Merci beaucoup!! – tjameson