2009-12-05 7 views
7

Quelles sont les meilleures pratiques pour stocker des ensembles imbriqués (comme des arbres de commentaires) dans MongoDB?Ensembles imbriqués MongoDB

Je veux dire, chaque commentaire peut avoir un commentaire de parent et les enfants commentaires (réponses).

les stocker comme ceci:

{ 
    title: "Hello", 
    body: "Please comment me!", 
    comments: [ 
     { 
      author: "Peter", 
      text: "Hi there", 
      answers: [ 
        { 
         author: "Peter", 
         text: "Hi there", 
         answers: [ 
           { author: "Ivan", text: "Hi there" }, 
           { author: "Nicholas", text: "Hi there" } 
         ] 
        }, 
        { author: "Ivan", text: "Hi there" }, 
        { author: "Nicholas", text: "Hi there" }, 
      ] 
     }, 
     { author: "Ivan", text: "Hi there" }, 
     { author: "Nicholas", text: "Hi there" }, 
    ] 
} 

est pas cool, parce que nous ne pouvons pas, par exemple, demander "tous les post qui sont commentées par Peter" sans map/reduce.

Répondre

3

Je pense qu'il n'y a pas de solution parfaite - cela dépend des opérations les plus importantes pour votre application. Je crois que Silicon Alley Insider stocke les commentaires imbriqués avec MongoDB par exemple. Cela rend la requête que vous mentionnez plus difficile.

Une option est stocker au niveau supérieur dans la publication d'une liste de tous les commentateurs dans un tableau. Pensez à cela comme des données dénormalisées. Ensuite, on peut facilement trouver tous les messages qui impliquent un certain intervenant. Ensuite, pour explorer, vous utilisez map/reduce ou db.eval() pour obtenir les informations de publication imbriquées.

Une autre remarque - si vous traitez un seul document, db.eval() est probablement plus léger que map/reduce. $ where est aussi une option mais peut être lent donc j'aime la liste additionnelle de commentateurs mentionnée ci-dessus - pas aussi il est facile d'indexer ce tableau aussi (voir 'Multikey' dans les docs).

Voir aussi: http://groups.google.com/group/mongodb-user/browse_thread/thread/df8250573c91f75a/e880d9c57e343b52?lnk=gst&q=trees#e880d9c57e343b52

2

Dans le lien de poste de dm Dwight Merriman mentions en utilisant une clé de chemin et faisant expression régulière

{ 
    path : "a.b.c.d.e.f" 
} 

Une autre façon de le faire serait avec des tableaux

{ 
    path : ["a", "b", "c", "d", "e", "f"] 
} 

db.test.ensureIndex({path: 1}) 

qui devrait le rendre assez rapide.

si chaque noeud ne peut être dans un seul chemin alors vous ne devez pas inquiéter de savoir où il se trouve dans la liste

db.test.find({path: "a"}) 

trouverait tous les enfants de « un »

Au lieu de noms de chemins, j'utiliserais probablement le _id des nœuds.

Mise à jour

  • une chose à faire attention est qu'un index ne peut avoir qu'un seul tableau en elle.
  • Attention à utiliser expliquer sur vos requêtes

    db.test.trouver ({chemin: {$ dans: [ "a", "b"]})

vous donne

db.test.find({path: {$in: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1 multi", 
     "nscanned" : 2, 
     "nscannedObjects" : 2, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ], 
         [ 
           "b", 
           "b" 
         ] 
       ] 
     } 
} 

mais

db.test.find({path: {$all: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1", 
     "nscanned" : 1, 
     "nscannedObjects" : 1, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ] 
       ] 
     } 
} 

utilise uniquement le premier élément et puis numérise tous les résultats correspondants pour b.
Si a est votre élément racine ou est dans la plupart de vos enregistrements, alors vous faites un balayage presque complet des enregistrements au lieu d'une requête d'index efficace.

Questions connexes