sql >> Base de Datos >  >> NoSQL >> MongoDB

¿La forma más eficiente de almacenar categorías anidadas (o datos jerárquicos) en Mongo?

Lo primero que debe decidir es exactamente qué tipo de árbol usará.

Lo más importante a considerar son sus datos y patrones de acceso. Ya ha declarado que el 90 % de todo su trabajo consistirá en realizar consultas y, por lo que parece (comercio electrónico), las actualizaciones solo las ejecutarán los administradores, muy probablemente en raras ocasiones.

Entonces, desea un esquema que le brinde el poder de consultar rápidamente a un niño a través de una ruta, es decir, Deportes -> Baloncesto -> Hombres, Deportes -> Tenis -> Mujeres, y realmente no necesita escalar realmente a las actualizaciones.

Como bien señaló, MongoDB tiene una buena página de documentación para esto:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ por lo que 10gen en realidad establece diferentes modelos y métodos de esquema para árboles y describe los principales altibajos de ellos.

El que debería llamar la atención si está buscando consultar fácilmente son las rutas materializadas:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Este es un método muy interesante para construir árboles, ya que para consultar el ejemplo que diste anteriormente sobre "Mujeres" en "Tenis", simplemente podrías hacer una expresión regular prefijada (que puede usar el índice:http://docs.mongodb.org/manual/reference/operator/regex/ ) así:

db.products.find({category: /^Sports,Tennis,Womens[,]/})

para encontrar todos los productos enumerados en una determinada ruta de su árbol.

Desafortunadamente, este modelo es realmente malo para actualizar, si mueve una categoría o cambia su nombre, debe actualizar todos los productos y podría haber miles de productos en una categoría.

Un mejor método sería albergar un cat_id en el producto y luego separe las categorías en una colección separada con el esquema:

{
    _id: ObjectId(),
    name: 'Women\'s',
    path: 'Sports,Tennis,Womens',
    normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}

Entonces, ahora sus consultas solo involucran la colección de categorías, lo que debería hacerlas mucho más pequeñas y de mayor rendimiento. La excepción a esto es cuando eliminas una categoría, los productos aún necesitarán ser tocados.

Entonces, un ejemplo de cambiar "Tenis" a "Badmin":

db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
    doc.path = doc.path.replace(/,Tennis/, ",Badmin");
    db.categories.save(doc);
});

Desafortunadamente, MongoDB no proporciona reflejos de documentos en la consulta en este momento, por lo que debe extraerlos del lado del cliente, lo que es un poco molesto, sin embargo, con suerte, no debería resultar en que se recuperen demasiadas categorías.

Y esto es básicamente cómo funciona realmente. Es un poco molesto actualizar, pero creo que el poder de poder consultar instantáneamente en cualquier ruta usando un índice es más adecuado para su escenario.

Por supuesto, el beneficio adicional es que este esquema es compatible con modelos de conjuntos anidados:http://en.wikipedia .org/wiki/Nested_set_model que he encontrado una y otra vez son increíbles para los sitios de comercio electrónico, por ejemplo, Tenis puede estar tanto en "Deportes" como en "Ocio" y desea múltiples rutas dependiendo de dónde proviene el usuario.

El esquema para rutas materializadas admite esto fácilmente simplemente agregando otra path , así de simple.

Espero que tenga sentido, bastante largo allí.