Sous-documents Mongoose vs schéma imbriqué

122

Je suis curieux de connaître les avantages et les inconvénients de l'utilisation de sous-documents par rapport à une couche plus profonde dans mon schéma principal:

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

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

ou

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

J'utilise actuellement des sous-documents partout mais je m'interroge principalement sur les problèmes de performances ou d'interrogation que je pourrais rencontrer.

cyberwombat
la source
J'essayais de taper une réponse pour vous, mais je n'ai pas trouvé comment. Mais donner un coup d' oeil ici: mongoosejs.com/docs/subdocs.html
gustavohenke
Voici une bonne réponse sur les considérations MongoDB à vous poser lors de la création de votre schéma de base de données: stackoverflow.com/questions/5373198/…
anthonylawson
Vous vouliez dire qu'il fallait également décrire le _iddomaine? Je veux dire, ce n'est pas un peu automatique si c'est activé?
Vadorequest
quelqu'un sait si le _idchamp des sous-documents est unique? (créé en utilisant la 2ème manière dans la question d'OP)
Saitama

Réponses:

72

Selon la documentation , c'est exactement la même chose. Cependant, l'utilisation d'un schéma ajouterait également un _idchamp (tant que vous ne l'avez pas désactivé) et utilisera vraisemblablement plus de ressources pour le suivi des sous-documents.

Syntaxe de déclaration alternative

Nouveau dans la v3 Si vous n'avez pas besoin d'accéder à l'instance de schéma de sous-document, vous pouvez également déclarer des sous-documents en passant simplement un objet littéral [...]

AndyL
la source
1
Mais j'ai essayé ça. Pourquoi les données des sous-documents ne sont pas stockées dans une collection séparée. Il est toujours stocké dans la collection mainDoc.
Fizer Khan
17
c'est ainsi que fonctionnent les sous-documents. ils sont incorporés à l'intérieur d'un document. avant de jouer avec mangouste, assurez-vous de bien comprendre le MongoDB sous-jacent.
AndyL
1
En ce qui concerne le schéma ajoutant _id, cela a du sens, mais j'ai créé un schéma avec un tableau de sous-documents et un tableau de littéraux d'objet et un _id a été ajouté aux deux. Le comportement a-t-il changé?
Drew Goodwin
@DrewGoodwin semble être comme ça depuis un moment: stackoverflow.com/questions/17254008/…
cheesemacfly
37

Si vous avez des schémas qui sont réutilisés dans différentes parties de votre modèle, il peut être utile de définir des schémas individuels pour les documents enfants afin de ne pas avoir à vous dupliquer.

Sonstone
la source
4
C'est une excellente réponse. Parfois, j'utilise des sous-documents dans plus d'un modèle, ou j'ai deux champs dans un modèle qui doit être distingué, mais qui ont toujours la même structure de sous-document.
Martin Hallén
2
vous devez également prendre en compte les avantages / inconvénients de la sauvegarde d'informations redondantes.
Sam Vloeberghs
25

Vous devez utiliser des documents incorporés s'il s'agit de documents statiques ou qui ne dépassent pas quelques centaines en raison de l'impact sur les performances. J'ai parlé de ce problème il y a un moment. Récemment, Asya Kamsky qui travaille comme architecte de solutions pour MongoDB avait écrit un article sur «l'utilisation de sous-documents».

J'espère que cela aidera à qui recherche des solutions ou les meilleures pratiques.

Article original sur http://askasya.com/post/largeembeddedarrays . Vous pouvez accéder à son profil stackoverflow sur https://stackoverflow.com/users/431012/asya-kamsky

Tout d'abord, nous devons réfléchir aux raisons pour lesquelles nous voudrions faire une telle chose. Normalement, je conseillerais aux gens d'intégrer des choses qu'ils veulent toujours récupérer lorsqu'ils récupèrent ce document. Le revers de la médaille est que vous ne souhaitez pas incorporer dans le document des éléments que vous ne souhaitez pas récupérer.

Si vous intégrez l'activité que j'exécute dans le document, cela fonctionnera très bien au début car toute mon activité est là et avec une seule lecture, vous pouvez récupérer tout ce que vous voudrez peut-être me montrer: "vous avez récemment cliqué dessus et ici sont vos deux derniers commentaires "mais que se passe-t-il après six mois et je me fiche de ce que j'ai fait il y a longtemps et vous ne voulez pas me les montrer à moins que je ne cherche spécifiquement une vieille activité?

Tout d'abord, vous finirez par renvoyer un document de plus en plus gros et en vous souciant d'une partie de plus en plus petite. Mais vous pouvez utiliser la projection pour ne renvoyer qu'une partie du tableau, le vrai problème est que le document sur le disque s'agrandira et qu'il sera toujours lu même si vous n'en restituerez qu'une partie à l'utilisateur final, mais puisque mon activité ne s'arrêtera pas tant que je serai actif, le document continuera de grandir et de grandir.

Le problème le plus évident avec cela est finalement que vous atteindrez la limite de 16 Mo de documents, mais ce n'est pas du tout ce qui devrait vous inquiéter. Un document qui ne cesse de croître entraînera des coûts de plus en plus élevés chaque fois qu'il devra être déplacé sur le disque, et même si vous prenez des mesures pour atténuer les effets de la fragmentation, vos écritures seront globalement inutilement longues, ce qui aura un impact sur les performances globales de l'ensemble de votre application.

Il y a une autre chose que vous pouvez faire qui va complètement tuer les performances de votre application et c'est d'indexer ce tableau toujours croissant. Cela signifie que chaque fois que le document avec ce tableau est déplacé, le nombre d'entrées d'index qui doivent être mis à jour est directement proportionnel au nombre de valeurs indexées dans ce document, et plus le tableau est grand, plus ce nombre sera élevé. être.

Je ne veux pas que cela vous effraie d'utiliser des tableaux lorsqu'ils conviennent bien au modèle de données - ils sont une fonctionnalité puissante du modèle de données de la base de données de documents, mais comme tous les outils puissants, il doit être utilisé dans les bonnes circonstances et il doit être utilisé avec précaution.

efkan
la source
3
Cela devrait être la meilleure réponse; c'est bon pour l'argent. Les propres livres blancs de MongoDB disent à peu près la même chose.
Jay Edwards
Cet article sur le modèle de seau complète ce dont Asya parle joliment. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern Je pense que le schéma subDoc dans la question d'OP fonctionnerait bien avec le modèle de seau.
plong0
13

En gros, créez une variable nestedDovet placez-la iciname: [nestedDov]

Version simple:

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

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

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

Exemple:

entrez la description de l'image ici

Wayne Chiu
la source
1
Cela ne répond pas du tout à la question de la performance.
cyberwombat le
J'ai édité un peu pour avoir plus de sens. Qu'est-ce que tu penses?
Wayne Chiu
3
La question n'est pas de savoir comment faire des schémas imbriqués. Il s'agit de savoir si Mongoose est plus performant avec des schémas imbriqués ou des sous-documents intégrés. Fondamentalement, nous parlons de points de repère ou de types ou de cas extrêmes où Mongoose préfère l'un à l'autre. Et comme le mentionne la réponse sélectionnée, cela ne semble pas faire de différence, du moins à partir de la V3.
cyberwombat le
17
Peut-être ne fonctionne pas pour l'OP, mais j'ai trouvé cela très utile. Merci.
Gene Higgins
C'est bien lorsque les 3 schémas sont déclarés dans un fichier .js, comment pouvons-nous le gérer lorsqu'ils sont déclarés dans 3 fichiers .js différents?
Satyam
9

Je pense que cela est traité ailleurs par plusieurs messages sur SO.

Juste un peu:

La grande clé est qu'il n'y a pas de réponse unique ici, seulement un ensemble de compromis assez complexes.

Vice-président Gates
la source
3
Peut-être que je ne formule pas correctement ma question - Il ne s'agit pas de savoir comment je devrais structurer ma base de données, mais plutôt de savoir comment utiliser un sous-schéma plutôt que d'écrire simplement le tableau dans une couche plus profonde. Ma principale raison d'utiliser un sous-schéma est que je peux utiliser des types de schémas personnalisés et les faire valider - quelque chose qui ne fonctionne pas avec les tableaux imbriqués (à partir d'une question précédente que j'avais sur SO). Autant que je sache, un subdoc est à peu près identique à un tableau imbriqué - je n'en connais tout simplement pas les éléments internes - si leur utilisation créerait des problèmes de performances ou autres.
cyberwombat
0

Il y a une différence entre les deux:

  • L'utilisation d'un schéma imbriqué est utile pour la validation.

  • Le schéma imbriqué peut être réutilisé dans d'autres schémas.

  • Le schéma imbriqué ajoute le champ '_id' au sous-document sauf si vous avez utilisé "_id: false"
Ahmad Zahabi
la source