web-dev-qa-db-fra.com

Implications Mongodb de la mise à jour par rapport au remplacement

J'ai lu cette question connexe , mais celle ci-dessous est différente. Le pilote mongodb c # possède une méthode ReplaceOne (& un équivalent asynchrone) sur la classe de collection de documents, qui peut être utilisée pour remplacer le contenu entier d'un document qui correspond à l'argument de filtre. L'alternative consiste à utiliser les méthodes UpdateOne ou UpdateMany (ou homologues asynchrones), ce qui nécessite la construction d'un UpdateDefinition<TDocument>.

Ma question concerne les implications du choix de l'une de ces méthodes par rapport à l'autre (remplacer vs mettre à jour), dans les cas où vous avez suffisamment de données d'entrée pour choisir l'une ou l'autre pour obtenir le même résultat. En d'autres termes, si j'ai l'intégralité du document d'origine et que je souhaite seulement mettre à jour une petite tranche de son contenu.

Le premier facteur auquel je peux penser est la charge utile envoyée au serveur de base de données. Bien que je n'ai lu aucune source de pilote mongodb c # et que je n'ai trouvé aucun document pour le vérifier, il semble que ReplaceOne pourrait devoir envoyer plus d'octets avec l'opération de mise à jour, en particulier pour les documents plus volumineux. Le Update... les méthodes semblent pouvoir s'en tirer avec une charge utile plus petite en envoyant uniquement des métadonnées de mise à jour pour les tranches du document qui nécessitent une modification (en plus des critères de filtrage, que les deux méthodes doivent envoyer). Quelqu'un peut-il vérifier s'il s'agit d'une hypothèse exacte?

Un autre facteur soulevé par un collègue est que le choix de la méthode (mise à jour ou remplacement) pourrait également affecter l'indexation des documents. L'hypothèse ici est que l'utilisation de ReplaceOne peut entraîner la reconstruction par la base de données de tous les index du document mis à jour, tandis que le Update... les méthodes contiennent suffisamment d'informations de modification des métadonnées pour éviter de reconstruire des index sur des champs qui ne font pas partie des métadonnées dans la définition de mise à jour. Quelqu'un peut-il vérifier si mongodb gère en interne la construction d'index de document différemment selon que le document est modifié à l'aide de remplacement ou de mise à jour?

Un troisième facteur nous est déjà apparu plusieurs fois, concernant les méthodes AddToSet et PullFilter sur le Update<TDefinition> classe. Il semble que le Update... les méthodes ne vous permettront pas de modifier un ensemble dans un document (comme un tableau json) en y ajoutant des éléments et en les supprimant en même temps; ces opérations doivent être envoyées individuellement, en utilisant 2 appels distincts vers le Update... méthode avec _ Update<TDefinition> instances (mais avec les mêmes arguments de filtre). La méthode ReplaceOne, dans ce cas, semble être le seul moyen de modifier ce type de document en une seule "transaction", au moins lors de l'utilisation du pilote C #. Nous utilisons actuellement Update... sur ReplaceOne pour l'instant car nous ne savons pas si l'alternative affecterait négativement l'indexation comme mentionné ci-dessus.

À part cela, quelles sont les implications supplémentaires qui pourraient conduire à choisir parmi la famille de méthodes ReplaceOne plutôt que Update... famille ou vice-versa? Encore une fois, cela suppose que vous disposez de suffisamment de données d'entrée (c'est-à-dire toutes les données du document) pour obtenir le même résultat avec l'une ou l'autre approche, cela ne vous dérange pas de changer d'état directement (via le remplacement), et cela ne vous dérange pas de créer des définitions de mongo (via la mise à jour) .

20
danludwig

Étant donné que les données mongo ne sont pas structurées, le principal avantage de replaceOne vs Update est qu'il est garanti que tous vos champs seront supprimés et remplacés par le nouveau document, ce qui rend la requête plus simple de votre part

1) Certes, mais le moindre de vos problèmes, les critères de recherche seront les mêmes dans les deux, mais replaceOne nécessitera que tout le document soit passé dans la requête, toujours utile lorsque vous avez le nouveau document complet et que vous voulez être sûr qu'il le sera fin de cette façon

2) réindexer lors du remplacement -> oui, replaceOne remplacer tout le document au lieu de mettre à jour un document existant, si vous mettez à jour sur l'élément qui se trouve sur l'index, l'index devra se réajuster au changement, mais avec replace, il devra toujours réadapter. l'indice _id n'est pas affecté par les deux opérations (je pense)

3) Si vous avez déjà la valeur que vous voulez être, vous n'auriez pas besoin de remplacer le document complet pour changer un seul champ, ce qui le rendra indexé par tous les champs, vous devez utiliser l'opération $ set pour cela, ce que vous pourriez penser comme un ReplaceOne pour un seul champ au lieu du document entier

https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/index.htmlhttps://docs.mongodb.com/manual/reference/ operator/update/set /

1
zero

Si elle est incorporée dans un service REST, la méthode replaceOne s'alignerait bien avec une opération PUT, où vous enverriez un objet entier dans votre corps de demande avec un identifiant d'objet, et cela pourrait alors être persistant dans la base de données dans son intégralité. La caractéristique distinctive d'une opération PUT étant qu'elle est idempotente (vous pouvez l'exécuter à plusieurs reprises). replaceOne prend une option upsert qui prend par défaut la valeur false, mais si cela ont été définies sur true (et les critères de recherche se trouvaient sur un champ uniquement indexé), cela rendrait l'opération répétable, que le document ait été supprimé indépendamment ou non.

L'opération de mise à jour s'apparente davantage à une opération POST, car elle met à jour une partie d'un document plutôt que de la remplacer entièrement. Elle prend également une option upsert, mais si le document a été supprimé par un autre processus, le document résultant pourrait être mal formé et la mise à jour pourrait échouer.

0
robjwilkins