2012-11-30 23 views
10

Angesichts der unten stehenden konkurrierenden Schemas mit bis zu 100.000 Freunden bin ich daran interessiert, die effizienteste für meine Bedürfnisse zu finden.MongoDB Embedded vs Array Subdokument Leistung

Doc1 (Index auf user_id)

{ 
"_id" : "…", 
"user_id" : "1", 
friends : { 
    "2" : { 
     "id" : "2", 
     "mutuals" : 3 
    } 
    "3" : { 
     "id" : "3", 
     "mutuals": "1" 
    } 
    "4" : { 
     "id" : "4", 
     "mutuals": "5" 
    } 
} 
} 

Doc2 (Verbindung Multi Schlüsselindex auf User_id & friends.id)

{ 
"_id" : "…", 
"user_id" : "1", 
friends : [ 
    { 
     "id" : "2", 
     "mutuals" : 3 
    }, 
    { 
     "id" : "3", 
     "mutuals": "1" 
    }, 
    { 
     "id" : "4", 
     "mutuals": "5" 
    } 
]} 

ich nicht auf die keine Informationen zu finden scheinen, Effizienz des Subfield-Retrieval. Ich weiß, dass Mongo Daten intern als BSON implementiert, also frage ich mich, ob das bedeutet, dass eine Projektionssuche ein binäres O (log n) ist?

Speziell, wenn eine user_id gefunden wird, um herauszufinden, ob ein Freund mit friend_id existiert, wie würden die zwei verschiedenen Abfragen in jedem Schema verglichen? (Angenommen, die oben genannten Indizes) Beachten Sie, dass es nicht wirklich wichtig ist, was zurückgegeben wird, nur dass nicht Null zurückgegeben wird, wenn der Freund existiert.

Doc1col.find({user_id : "…"}, {"friends.friend_id"}) 
Doc2col.find({user_id : "…", "friends.id" : "friend_id"}, {"_id":1}) 

Auch von Interesse ist, wie der $ set Modifier funktioniert. Wie funktioniert das Lookup auf der friends.friend_id für Schema 1 bei der Abfrage Doc1col.update({user_id : "…"}, {"$set" : {"friends.friend_id.mutuals" : 5})? Ist das eine O (log n) -Operation (wobei n die Anzahl der Freunde ist)?

Für Schema 2, wie würde die Abfrage Doc2col.update({user_id : "…", "friends.id" : "friend_id"}, {"$set": {"friends.$.mutuals" : 5}) mit der obigen vergleichen?

+3

Gehen Sie mit dem Array-Stil (Doc2) als dynamische Schlüssel sind fast nie der richtige Ansatz. Verwende auch keine smarten Anführungszeichen (es ist keine legale Syntax und es ist schwer zu lesen). – JohnnyHK

+1

Ich nehme an, Doc2 wird wie ein paar Bytes zusätzlichen Speicherplatzes verbrauchen, aber da @JohnnyHK sagt, Doc1 ist nicht wirklich ein guter Ansatz, vertraut mir die Menge der Fragen von Leuten, die Doc1 benutzen, dann erkennen, dass sie zu Doc2 umziehen müssen mit ihrem Schema ... – Sammaye

+0

Danke für den Rat. @Sammaye warum wird Doc2 ein paar Bytes zusätzlichen Speicherplatz verbrauchen? Beziehen Sie sich auf den Index? Btw intelligente Zitate waren ein Fehler von Kopie einfügen –

Antwort

1

doc1 ist vorzuziehen, wenn die primären Anforderungen darin bestehen, die Daten in einem übersichtlichen Paket darzustellen. sein einfache nur die gewünschten Daten zu filtern, um eine Projektion {}, {friends.2 : 1}

doc2 ist Ihr stärkstes Spiel verwenden, da Ihr Anwendungsfall nicht über das Ergebnis Hinweis schert, dass es nicht wirklich wichtig, das tut, was zurückgegeben und Indizierung beschleunigen wird den Abruf .

oben auf dieser doc2 erlaubt es, die viel saubere Syntax

db.doc2.findOne({user_id: 1, friends.id : 2}) 

gegen

db.doc1.findOne({ $and : [{ user_id: 1 }, { "friends.2" : {$exists: true} }] }) 

auf abschließende Bemerkung, jedoch kann man ein sparse index auf doc1 (und verwendet $ vorhanden) erstellen, aber Ihre Möglichkeit von 100.000 Freunden - jeder Freund brauchte einen spärlichen Index - macht das absurd. im Gegensatz zu einer angemessenen Anzahl von Einträgen sagen Demographie Geschlecht [männlich, weiblich], Altersgruppen [0-10,11-16,25-30, ..] oder mehr impt Dinge [Gin, Whisky, Wodka, ...]