¿Cuál es la diferencia entre findAndModify y actualizar en MongoDB?

175

Estoy un poco confundido por el findAndModifymétodo en MongoDB. ¿Cuál es la ventaja sobre el updatemétodo? Para mí, parece que solo devuelve el artículo primero y luego lo actualiza. Pero, ¿por qué debo devolver el artículo primero? Leí el MongoDB: la guía definitiva y dice que es útil para manipular colas y realizar otras operaciones que necesitan atomicidad de estilo get-and-set. Pero no entendí cómo logra esto. ¿Alguien puede explicarme esto?

chaonextdoor
fuente

Respuestas:

153

Si busca un elemento y luego lo actualiza, puede haber una actualización por otro hilo entre esos dos pasos. Si primero actualiza un elemento y luego lo recupera, puede haber otra actualización intermedia y obtendrá un elemento diferente al que actualizó.

Hacerlo "atómicamente" significa que tiene la garantía de que está recuperando exactamente el mismo elemento que está actualizando, es decir, no puede ocurrir ninguna otra operación intermedia.

Asya Kamsky
fuente
66
Todavía estoy un poco confundido. ¿Cómo findAndModifygarantiza que no haya otra operación de actualización que interfiera con ella?
chaonextdoor
78
@chaonextdoor findAndModify adquiere un bloqueo a la base de datos cuando inicia la operación para que ninguna otra operación pueda procesar cuando se está ejecutando. Cuando termina la operación, libera el bloqueo.
Lycha
44
findAndModify en realidad no obtiene un bloqueo hasta que la parte de modificación de la solicitud. Por lo tanto, es posible que varios procesos puedan actualizar el mismo registro.
Mark Unsworth
55
@MarkUnsworth abre un caso de soporte con 10gen: si hay un error en el bloqueo con findAndModify, puedo garantizar que los ingenieros querrán solucionarlo lo antes posible. Si ese fuera el caso, veríamos a muchas personas informar este comportamiento, pero findAndModify funciona según lo diseñado para casi todos los que lo usan, casos en los que parecía que no se redujo a errores de lógica o implementación en el lado del cliente , pero, por supuesto, en el software complejo siempre puede haber un error.
Asya Kamsky
44
@AsyaKamsky Estaba pensando en discutir contigo pero luego me di cuenta de que estás en lo correcto, así que ahora estoy pensando en disculparme. ¡Lo siento!
funkyeah
54

findAndModify devuelve el documento, la actualización no.

Si entendí Dwight Merriman (uno de los autores originales de mongoDB) correctamente, usar la actualización para modificar un solo documento, es decir ("multi": falso} también es atómico. Actualmente, también debería ser más rápido que hacer la actualización equivalente usando findAndModify.

Yaniv
fuente
31

De los documentos de MongoDB (énfasis agregado):

  • Por defecto, ambas operaciones modifican un solo documento. Sin embargo, el método update () con su opción múltiple puede modificar más de un documento .

  • Si varios documentos coinciden con los criterios de actualización, para findAndModify (), puede especificar una clasificación para proporcionar alguna medida de control sobre qué documento actualizar. Con el comportamiento predeterminado del método update (), no puede especificar qué documento único actualizar cuando coinciden varios documentos.

  • Por defecto, el método findAndModify () devuelve la versión pre-modificada del documento . Para obtener el documento actualizado, use la nueva opción. El método update () devuelve un objeto WriteResult que contiene el estado de la operación. Para devolver el documento actualizado, use el método find (). Sin embargo, otras actualizaciones pueden haber modificado el documento entre su actualización y la recuperación del documento. Además, si la actualización modificó solo un documento único pero coincidieron varios documentos, deberá utilizar una lógica adicional para identificar el documento actualizado.

  • Antes de MongoDB 3.2, no puede especificar una preocupación de escritura para encontrarAndModify () para anular la preocupación de escritura predeterminada, mientras que puede especificar una preocupación de escritura para el método update () desde MongoDB 2.6.

Al modificar un solo documento, findAndModify () y el método update () actualizan atómicamente el documento.

Tamlyn
fuente
1
Siempre puede especificar la preocupación de escritura para actualizar la operación. Además, desde 3.2 (3.1.1 técnicamente) también puede especificar la preocupación de escritura para findAndModify. jira.mongodb.org/browse/SERVER-6558
Asya Kamsky
He encontrado que en MongDB 3.6, aunque los estados de documentación findAndModify()modifican de manera predeterminada solo una ficha y update()pueden actualizar una o más fichas, cuando uso una arrayFilters, findAndModify()actualiza todas las coincidencias. Tal vez es un error?
WesternGun
No hay ningún error: arrayFilters le permite actualizar varios elementos de la matriz, pero todavía están en un solo documento.
Asya Kamsky
10

Una clase útil de casos de uso son los contadores y casos similares. Por ejemplo, eche un vistazo a este código (una de las pruebas de MongoDB): find_and_modify4.js .

Por lo tanto, findAndModifyincrementa el contador y obtén su valor incrementado en un solo paso. Compare: si (A) realiza esta operación en dos pasos y otra persona (B) realiza la misma operación entre sus pasos, entonces A y B pueden obtener el mismo último valor de contador en lugar de dos diferentes (solo un ejemplo de posibles problemas).

Roman Kuzmin
fuente
0

Utilizamos findAndModify () para operaciones de contador (inc o dec) y otros casos de mutación de campos únicos. Al migrar nuestra aplicación de Couchbase a MongoDB, encontré que esta API reemplaza el código que hace GetAndlock (), modifica el contenido localmente, reemplaza () para guardar y Get () nuevamente para recuperar el documento actualizado. Con mongoDB, acabo de usar esta API única que devuelve el documento actualizado.

Manju Kori
fuente