En MongoDB el db.collection.findAndModify()
El método modifica y devuelve un único documento.
La collection
part es el nombre de la colección con la que realizar la operación.
Ejemplo
Supongamos que tenemos una colección llamada pets
que contiene los siguientes documentos:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Podemos usar db.collection.findAndModify()
para modificar uno de esos documentos.
db.pets.findAndModify({
query: { type: "Dog" },
update: { type: "Cow" }
})
Resultado:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" }
Por defecto, devuelve el documento original (no la versión modificada).
Tenga en cuenta que solo se actualizó un perro, aunque hay dos perros en la colección.
Revisemos la colección.
db.pets.find()
Resultado:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Podemos ver que el primer documento ahora contiene una vaca en lugar de un perro. Sin embargo, también podemos ver que el campo del nombre del documento ha desaparecido.
Eso es porque, cuando pasa un documento a update
argumento, db.collection.findAndModify()
realiza un reemplazo.
Uso de un operador de actualización
Si quisiéramos actualizar un campo, pero dejar el resto del documento intacto, necesitaríamos incluir las expresiones relevantes del operador de actualización en nuestro documento.
Con la colección en su estado actual, realicemos otro findAndModify()
operación en su contra, pero esta vez usaremos el $set
operador de actualización para establecer solo el campo que queremos cambiar.
db.pets.findAndModify({
query: { type: "Dog" },
update: { $set: { type: "Horse" } }
})
Resultado:
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
Esta vez se actualizó el perro restante.
Echemos un vistazo a la colección.
db.pets.find()
Resultado:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Esta vez se actualizó el campo relevante y el resto del documento permaneció intacto.
Devolver el Documento Modificado
De forma predeterminada, el documento original se devuelve cuando usa db.collection.findAndModify()
.
Si prefiere que le devuelvan el documento modificado, use el new
parámetro.
Por defecto, esto es new: false
, lo que hace que se devuelva el documento original. Pero especificando new: true
da como resultado que se devuelva el documento modificado.
Hagamos otra modificación, pero esta vez usaremos new: true
.
db.pets.findAndModify({
query: { name: "Meow" },
update: { $set: { name: "Scratch" } },
new: true
})
Resultado:
{ "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Así que renombramos Meow
Scratch
y la salida refleja nuestros cambios.
Inserciones
Puede realizar upserts especificando upsert: true
.
Un upsert es una opción que puede usar en las operaciones de actualización. Si el documento especificado no existe, se inserta uno nuevo. Si lo hace existe, el documento original se actualiza (y no se inserta ningún documento).
Ejemplo usando upsert: false
Aquí hay un ejemplo de intentar actualizar un documento inexistente cuando upsert: false
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true
})
Resultado:
null
El documento no existía en la colección, por lo que findAndModify()
devolvió null
. Aunque no especificamos upsert: false
, sabemos que era falso porque ese es el valor predeterminado (es decir, ese es el valor que se usa cuando no especifica una opción upsert).
Si echamos otro vistazo a la colección, podemos ver que el documento no fue alterado.
db.pets.find()
Resultado:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Ejemplo usando upsert: true
Ahora aquí está de nuevo, pero esta vez especificamos upsert: true
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true,
upsert: true
})
Resultado:
{ "_id" : 4, "name" : "Fetch", "type" : "Dog" }
Esta vez se altera un nuevo documento y vemos el documento alterado como salida (porque especificamos new: true
).
Revisemos la colección nuevamente.
db.pets.find()
Resultado:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" } { "_id" : 4, "name" : "Fetch", "type" : "Dog" }
Entonces podemos ver que el nuevo documento fue alterado.
El parámetro arrayFilters
Cuando trabaje con arreglos, puede usar los arrayFilters
parámetro junto con el posicional $
operador para determinar qué elementos de la matriz actualizar. Esto le permite actualizar un elemento de matriz en función de su valor, incluso si no conoce su posición.
Por ejemplo, supongamos que tenemos una colección llamada players
con los siguientes documentos:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
Podríamos ejecutar la siguiente consulta para actualizar solo aquellos elementos de la matriz que tengan un valor superior a cierta cantidad (en este caso, 10).
db.players.findAndModify({
query: { scores: { $gte: 10 } },
update: { $set: { "scores.$[e]" : 10 } },
arrayFilters: [ { "e": { $gte: 10 } } ]
})
Resultado:
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
Como era de esperar, esto solo actualiza un documento, aunque dos documentos coinciden con los criterios.
Así es como se ven los documentos ahora.
db.players.find()
Resultado:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 10, 10 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
El documento 2 tenía dos elementos de matriz actualizados, porque esos elementos coincidían con los criterios.
Más información
db.collection.findAndModify()
El método también acepta otros parámetros, como writeConcern
, collection
, bypassDocumentValidation
y más.
Consulte la documentación de MongoDB para db.collections.findAndModify()
para más información.