Quelle est la différence entre findAndModify et update dans MongoDB?


175

Je suis un peu confus par la findAndModifyméthode de MongoDB. Quel est l'avantage par rapport à la updateméthode? Pour moi, il semble que cela retourne simplement l'élément en premier, puis le met à jour. Mais pourquoi dois-je d'abord retourner l'article? J'ai lu le MongoDB: le guide définitif et il dit qu'il est pratique pour manipuler les files d'attente et effectuer d'autres opérations qui nécessitent une atomicité de style get-and-set. Mais je n'ai pas compris comment il y parvient. Quelqu'un peut-il m'expliquer cela?

Réponses:


153

Si vous récupérez un élément et le mettez à jour, il peut y avoir une mise à jour par un autre thread entre ces deux étapes. Si vous mettez d'abord à jour un élément, puis que vous le récupérez, il peut y avoir une autre mise à jour entre les deux et vous récupérerez un élément différent de celui que vous avez mis à jour.

Le faire "atomiquement" signifie que vous êtes assuré de récupérer exactement le même élément que vous mettez à jour - c'est-à-dire qu'aucune autre opération ne peut se produire entre les deux.


6
Je suis encore un peu confus. Comment findAndModifygarantit-il qu'aucune autre opération de mise à jour ne l'interférera?
chaonextdoor

78
@chaonextdoor findAndModify acquiert un verrou sur la base de données lorsqu'il démarre l'opération afin qu'aucune autre opération ne puisse être traitée lorsqu'elle est en cours d'exécution. Lorsqu'il a terminé l'opération, il libère le verrou.
Lycha

4
findAndModify n'obtient pas de verrou avant la partie de modification de la requête. Il est donc possible que plusieurs processus puissent mettre à jour le même enregistrement.
Mark Unsworth

5
@MarkUnsworth ouvre un dossier de support avec 10gen - s'il y a un bogue de verrouillage avec findAndModify, je peux vous garantir que vos ingénieurs voudront le réparer dès que possible. Si tel était le cas, nous verrions beaucoup de gens signaler ce comportement, mais findAndModify fonctionne comme conçu pour à peu près tout le monde qui l'utilise - des cas où il semblait que cela ne se résumait pas à des bogues de logique ou d'implémentation côté client , mais bien sûr, dans les logiciels complexes, il peut toujours y avoir un bogue.
Asya Kamsky

4
@AsyaKamsky J'envisageais de me disputer avec vous mais j'ai ensuite réalisé que vous aviez raison, alors maintenant je pense que je devrais m'excuser. Désolé!
funkyeah

54

findAndModify renvoie le document, la mise à jour ne le fait pas.

Si j'ai bien compris Dwight Merriman (l'un des auteurs originaux de mongoDB), utiliser update pour modifier un seul document ie ("multi": false} est également atomique. Actuellement, cela devrait aussi être plus rapide que de faire la mise à jour équivalente en utilisant findAndModify.


31

À partir de la documentation MongoDB (emphase ajoutée):

  • Par défaut, les deux opérations modifient un seul document. Cependant, la méthode update () avec son option multi peut modifier plus d'un document .

  • Si plusieurs documents correspondent aux critères de mise à jour, pour findAndModify (), vous pouvez spécifier un tri pour fournir une mesure de contrôle sur le document à mettre à jour. Avec le comportement par défaut de la méthode update (), vous ne pouvez pas spécifier le document unique à mettre à jour lorsque plusieurs documents correspondent.

  • Par défaut, la méthode findAndModify () renvoie la version pré-modifiée du document . Pour obtenir le document mis à jour, utilisez la nouvelle option. La méthode update () renvoie un objet WriteResult qui contient l'état de l'opération. Pour renvoyer le document mis à jour, utilisez la méthode find (). Cependant, d'autres mises à jour peuvent avoir modifié le document entre votre mise à jour et la récupération du document. De plus, si la mise à jour n'a modifié qu'un seul document mais que plusieurs documents correspondent, vous devrez utiliser une logique supplémentaire pour identifier le document mis à jour.

  • Avant MongoDB 3.2, vous ne pouvez pas spécifier un problème d'écriture à findAndModify () pour remplacer le problème d'écriture par défaut, alors que vous pouvez spécifier un problème d'écriture dans la méthode update () depuis MongoDB 2.6.

Lors de la modification d'un seul document, findAndModify () et la méthode update () mettent à jour le document de manière atomique.


1
Vous pouvez toujours spécifier une préoccupation d'écriture pour l'opération de mise à jour. De plus, depuis 3.2 (3.1.1 techniquement), vous pouvez également spécifier une préoccupation d'écriture pour findAndModify. jira.mongodb.org/browse/SERVER-6558
Asya Kamsky

J'ai trouvé que dans MongDB 3.6, bien que le doc déclare findAndModify()par défaut ne modifie qu'un seul document et update()puisse mettre à jour un ou plusieurs documents, lorsque j'utilise un arrayFilters, findAndModify()met à jour toutes les correspondances. C'est peut-être un bug ??
WesternGun

Il n'y a pas de bogue - arrayFilters vous permet de mettre à jour plusieurs éléments de tableau mais ils sont toujours dans un seul document.
Asya Kamsky

10

Les compteurs et les cas similaires sont une classe utile de cas d'utilisation. Par exemple, jetez un œil à ce code (l'un des tests MongoDB): find_and_modify4.js .

Ainsi, avec findAndModifyvous incrémentez le compteur et obtenez sa valeur incrémentée en une seule étape. Comparez: si vous (A) effectuez cette opération en deux étapes et que quelqu'un d'autre (B) fait la même opération entre vos étapes, A et B peuvent obtenir la même dernière valeur de compteur au lieu de deux différentes (juste un exemple de problèmes possibles).


0

Nous avons utilisé findAndModify () pour les opérations de comptage (inc ou dec) et d'autres champs uniques mutent les cas. En migrant notre application de Couchbase vers MongoDB, j'ai trouvé cette API pour remplacer le code qui fait GetAndlock (), modifier le contenu localement, replace () pour enregistrer et Get () à nouveau pour récupérer le document mis à jour. Avec mongoDB, je viens d'utiliser cette API unique qui renvoie le document mis à jour.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.