2010-12-13 8 views
1

Dies ist meine erste Frage hier auf Stackoverflow, also hoffe ich, dass ich das korrekte Protokoll befolge.Kann ich CouchDB-Dokumente mit gemeinsamen Schlüsseln bestellen?

Ich erstelle ein einfaches Browserspiel basierend auf CouchDB und NodeJS. In meinem Spiel können Benutzer mehrere Charaktere haben. Ich habe beschlossen, die Spieler von ihren Charakteren in der Datenbank zu trennen, weil ich selten Benutzerkontodaten (E-Mail, echter Name, usw.) mit ihren Charakterdaten verbinden muss. Wie auch immer, hier ist mein Problem:

Ich möchte in der Lage sein, eine Ansicht zu erstellen, die alle Zeichen zurückgibt, die von einem Player gesteuert werden. In diesem Dokument wird eine Eigenschaft namens "Eigentümer" angezeigt. Ich stelle fest, dass der einfachste Weg, dies zu tun, darin besteht, eine Ansicht zu erstellen, die eine Liste aller Charaktere zurückgibt, die nach Eigentümer kategorisiert sind.

meinen Code Hier ist so weit:

Funktion (doc) { emit (doc.owner, doc); }

Ich versuche, ein Ergebnis wie dieses zu erhalten (beachten Sie, dies vereinfacht, ich weiß, CouchDB andere Daten in der Ausgabe enthält):

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

Müssen Schlüssel eindeutig sein? Gibt mir mein Code das gewünschte Ergebnis?

Ich bin nicht mit der Idee der Trennung der Daten verheiratet, und ich könnte alternativ nur die Zeichen unter dem Benutzerdokument und nur zwei Ansichten erstellen, eine, die nur die Benutzerkonto Daten ausstrahlen würde und die Zeichendaten und verzichten ein anderes, um nur die Zeichendaten auszugeben und die Benutzerdaten wegzulassen, aber das erscheint mir ein wenig peinlich. Ich würde lieber die Daten getrennt halten, weil ich vielleicht andere Ansichten schreiben muss, die für die Charakterdaten spezifisch sind, und es scheint, dass es besser organisiert wäre, wenn ich die Charaktere von den Spielern in der Datenbank trennen würde.

Zu einem verwandten Hinweis, gibt es eine Möglichkeit, die Antworten zu filtern, indem Sie einen zweiten Parameter übergeben? Ich nehme an, dass dies die Effizienz einer Ansicht negiert und dass ich in diesem Fall wahrscheinlich eine temporäre Ansicht verwenden sollte. Mein Problem dabei ist, dass möglicherweise eine große Datenmenge von dieser Ansicht zurückgegeben wird (die gesamte Datenbank tatsächlich), die bei der Übertragung über HTTP sehr langsam sein könnte, zumal ich die meisten Daten nicht benötige.

Eine andere mögliche Lösung ist das Speichern der _id jedes Zeichens, das ein Benutzer als Eigenschaft in der Benutzerkontendatenbank steuert. Das scheint mir vernünftig genug zu sein, aber wenn es eine andere gibt, oder wenn ich es wage "bessere" Optionen zu nennen, dann würde ich es gerne hören.

Was wäre die beste Lösung für dieses Problem?

Vielen Dank im Voraus für Ihre Hilfe.

+0

wow, deine erste Frage und jetzt bist du 10k + :) ... – TimoSolo

Antwort

4

Sie sind auf dem richtigen Weg. Wenn Sie dies tun möchten mit einem reduzieren, können Sie diese Karte definieren:

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

Und das Reduce:

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

Diese zurückkehren sollte direkt, was Sie gefragt, aber kaum optimal: die Aussicht muss viele Daten für die Map- und Reduce-Teile speichern ...

Stattdessen habe ich eine Karte gehen würde ohne Reduce, wie folgt aus:

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

Diese Karte, wenn sie mit include_docs=true abgefragt, würde Zeilen zurück, die wie folgt aussehen:

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

Der Server Die Ladung ist leichter, und Sie können die Charaktere immer noch nach Spieler gruppieren, indem Sie im Ergebnis die key verwenden, wenn Sie das wirklich brauchen. Die Ergebnisse werden nach key, dann nach id sortiert.

Sie können diese Ansicht mit startkey und endkey abfragen, die beide der Spieler-ID entsprechen, um alle Zeichen eines Spielers zu erhalten. Wenn Sie nur die Zeichenbezeichner benötigen, fügen Sie include_docs=false hinzu, und der schwere doc-Teil wird nicht gesendet.

+0

Ich denke, ich werde ein doc-Design für beide Lösungen erstellen und beide ausprobieren, um zu sehen, was ich besser mag. Vielen Dank!! – tjameson

Verwandte Themen