Subdocumentos de mangosta vs esquema anidado


122

Tengo curiosidad por los pros y los contras de usar subdocumentos frente a una capa más profunda en mi esquema principal:

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});

o

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

Actualmente estoy usando subdocs en todas partes, pero me pregunto principalmente sobre problemas de rendimiento o consultas que pueda encontrar.


Estaba tratando de escribir una respuesta para ti, pero no pude encontrar cómo. Pero eche un vistazo aquí: mongoosejs.com/docs/subdocs.html
gustavohenke

Aquí hay una buena respuesta sobre las consideraciones de MongoDB que debe preguntarse al crear su esquema de base de datos: stackoverflow.com/questions/5373198/…
anthonylawson

¿Querías decir que también se requiere describir el _idcampo? Quiero decir, ¿no es algo automático si está habilitado?
Vadorequest

¿Alguien sabe si el _idcampo de los subdocumentos es único? (creado usando la segunda forma en la pregunta de OP)
Saitama

Respuestas:


72

Según los documentos , es exactamente lo mismo. Sin embargo, usar un esquema también agregaría un _idcampo (siempre que no lo tenga deshabilitado), y presumiblemente usa algunos recursos más para rastrear subdocs.

Sintaxis de declaración alternativa

Nuevo en v3 Si no necesita acceso a la instancia de esquema de subdocumento, también puede declarar subdocumentos simplemente pasando un objeto literal [...]


1
Pero intenté esto. Por qué los datos de los subdocumentos no se almacenan en una colección separada. Siempre se almacena dentro de la colección mainDoc.
Fizer Khan

17
así es como funcionan los subdocumentos. están incrustados dentro de un documento. antes de jugar con mangosta, asegúrese de comprender el MongoDB subyacente.
AndyL

1
Con respecto al esquema que agrega _id, eso tiene sentido, pero creé un esquema con una matriz de subdocumentos y una matriz de objetos literales y se agregó un _id a ambos. ¿Ha cambiado el comportamiento?
Drew Goodwin

@DrewGoodwin parece que ha sido así por un tiempo: stackoverflow.com/questions/17254008/…
cheesemacfly

37

Si tiene esquemas que se reutilizan en varias partes de su modelo, entonces podría ser útil definir esquemas individuales para los documentos secundarios para que no tenga que duplicarse.


4
Esta es una gran respuesta. A veces utilizo subdocumentos en más de un modelo, o tengo dos campos en un modelo que deben distinguirse, pero aún tienen la misma estructura de subdocumentos.
Martin Hallén

2
También debe considerar los beneficios / desventajas de guardar información redundante.
Sam Vloeberghs

25

Debe utilizar documentos incrustados si son documentos estáticos o que no son más de unos pocos cientos debido al impacto en el rendimiento. He analizado ese tema hace un tiempo. Recientemente, Asya Kamsky, que trabaja como arquitecto de soluciones para MongoDB, había escrito un artículo sobre "uso de subdocumentos".

Espero que eso ayude a quienes buscan soluciones o las mejores prácticas.

Publicación original en http://askasya.com/post/largeembeddedarrays . Puede acceder a su perfil de stackoverflow en https://stackoverflow.com/users/431012/asya-kamsky

Primero que nada, tenemos que considerar por qué querríamos hacer tal cosa. Normalmente, recomendaría a las personas que incorporen cosas que siempre quieran recuperar cuando obtengan este documento. La otra cara de la moneda es que no desea incrustar cosas en el documento que no desea recuperar.

Si inserta la actividad que realizo en el documento, funcionará muy bien al principio porque toda mi actividad está allí y con una sola lectura puede recuperar todo lo que podría querer mostrarme: "recientemente hizo clic en esto y aquí son tus dos últimos comentarios "pero ¿qué pasa después de que pasen seis meses y no me importen las cosas que hice hace mucho tiempo y no quieres mostrármelas a menos que vaya específicamente a buscar alguna actividad antigua?

Primero, terminará devolviendo un documento cada vez más grande y preocupándose por una parte cada vez más pequeña. Pero puede usar la proyección para devolver solo parte de la matriz, el verdadero problema es que el documento en el disco se hará más grande y aún se leerá todo, incluso si solo va a devolver una parte al usuario final, pero dado que mi actividad no se detendrá mientras esté activo, el documento seguirá creciendo y creciendo.

El problema más obvio con esto es que eventualmente alcanzará el límite de documentos de 16 MB, pero eso no es en absoluto lo que debería preocuparle. Un documento que crece continuamente tendrá un costo cada vez más alto cada vez que tenga que ser reubicado en el disco, e incluso si toma medidas para mitigar los efectos de la fragmentación, sus escrituras serán en general innecesariamente largas, lo que afectará el rendimiento general de toda su aplicación.

Hay una cosa más que puede hacer que matará por completo el rendimiento de su aplicación y es indexar esta matriz en constante aumento. Lo que eso significa es que cada vez que se reubica el documento con esta matriz, la cantidad de entradas de índice que deben actualizarse es directamente proporcional a la cantidad de valores indexados en ese documento, y cuanto mayor sea la matriz, mayor será ese número. ser.

No quiero que esto le impida usar matrices cuando se ajustan bien al modelo de datos; son una característica poderosa del modelo de datos de la base de datos de documentos, pero como todas las herramientas poderosas, debe usarse en las circunstancias adecuadas. y debe usarse con cuidado.


3
Esta debería ser la respuesta principal; es un golpe en el dinero. Los propios informes técnicos de MongoDB dicen más o menos lo mismo.
Jay Edwards

Este artículo sobre Bucket Pattern complementa muy bien lo que Asya habla. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern Creo que el esquema subDoc en la pregunta de OP funcionaría bien con Bucket Pattern.
plong0

13

Básicamente, crea una variable nestedDovy ponla aquí.name: [nestedDov]

Versión simple:

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});

Ejemplo JSON

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}

Ejemplo:

ingrese la descripción de la imagen aquí


1
Eso no responde en absoluto a la cuestión de cuál es el rendimiento.
cyberwombat

He editado un poco para que tenga más sentido. ¿Qué piensas?
Wayne Chiu

3
La pregunta no es cómo hacer esquemas anidados. Es una discusión sobre si Mongoose es más eficiente con esquemas anidados o subdocumentos incorporados. Básicamente, estamos hablando de puntos de referencia o clases o casos extremos en los que Mongoose prefiere uno al otro. Y como menciona la respuesta seleccionada, no parece haber ninguna diferencia, al menos a partir de la V3.
cyberwombat

17
Quizás no funcione para el OP, pero encontré esto muy útil. Gracias.
Gene Higgins

Esto es bueno cuando los 3 esquemas se declaran en un archivo .js, ¿cómo podemos manejarlo cuando se declaran en 3 archivos .js diferentes?
Satyam

9

Creo que esto se maneja en otros lugares mediante publicaciones múltiples en SO.

Sólo algunos:

La gran clave es que aquí no hay una respuesta única, solo un conjunto de compensaciones bastante complejas.


3
Quizás no estoy formulando mi pregunta correctamente: esta no es una cuestión de cómo debería estructurar mi base de datos, sino más bien los aspectos internos del uso de un subesquema en lugar de simplemente escribir la matriz en una capa más profunda. Mi causa principal para usar un subesquema es que puedo hacer uso de tipos de esquemas personalizados y hacer que validen, algo que no funciona con matrices anidadas (de una pregunta anterior que tenía en SO). Por lo que puedo decir, un subdoc es más o menos lo mismo que una matriz anidada, simplemente no conozco sus partes internas, si usarlos crearía problemas de rendimiento o algo así.
cyberwombat

0

Hay alguna diferencia entre los dos:

  • El uso de un esquema anidado es útil para la validación.

  • El esquema anidado se puede reutilizar en otros esquemas.

  • El esquema anidado agrega el campo '_id' al subdocumento a menos que haya usado "_id: false"
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.