Pregunta

¿Cuáles son las mejores prácticas para almacenar conjuntos anidados (como árboles de comentarios) en MongoDB?

Quiero decir, cada comentario puede tener un comentario de los padres y comentarios de los niños (respuestas).

Almacenándolos así:

{
   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" },
   ]
}

no está bien, porque no podemos, por ejemplo, solicitar "todas las publicaciones comentadas por Peter" sin map/reduce.

¿Fue útil?

Solución

Creo que no hay una solución perfecta - depende de lo que las operaciones son más importantes para su aplicación. Creo que almacena Silicon Alley Insider comentarios anidados con MongoDB por ejemplo. Eso tiene la consulta se menciona más duro.

Una opción es almacenar a nivel superior en el puesto de una lista de todos los comentaristas de una matriz. Pensar en que los datos que no normalizados. Entonces uno puede encontrar fácilmente todos los empleos que implican un cierto comentarista. Luego de perforar hacia abajo, se utiliza un mapa / reducir o db.eval () para obtener la información posterior anidado en su interior.

Otra nota - si se trata de un documento único, db.eval () es probablemente más ligero que el mapa / reducir. $, Donde también es una opción, pero puede ser lento, así que como la 'lista de comentaristas' adicional mencionado anteriormente -. No es también fácil de índice de esa matriz también (ver 'Multikey' en la documentación)

Vea también: http: // grupos. google.com/group/mongodb-user/browse_thread/thread/df8250573c91f75a/e880d9c57e343b52?lnk=gst&q=trees#e880d9c57e343b52

Otros consejos

En el enlace de la publicación de DM, Dwight Merriman menciona el uso de una clave de ruta y la realización de coincidencias de expresiones regulares.

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

Otra forma de hacer esto sería con matrices.

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

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

eso debería hacerlo bastante rápido.

Si cada nodo solo puede estar en una única ruta, entonces no tendría que preocuparse por dónde se encuentra en la lista.

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

encontraría todos los hijos de "a"

En lugar de nombres de rutas, probablemente usaría el _id de los nodos.

Actualizar

  • Una cosa con la que hay que tener cuidado es que un índice sólo puede tener una matriz.
  • Tenga cuidado al utilizar explicar en sus consultas.

    db.test.find({ruta:{$en:["a", "b"]})

te dio

 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"
                        ]
                ]
        }
}

pero

 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"
                        ]
                ]
        }
}

solo usa el primer elemento y luego escanea todos los resultados coincidentes para b.
Si a es su elemento raíz o está en la mayoría de sus registros, entonces está realizando un escaneo casi completo de los registros en lugar de una consulta de índice eficiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top