Tal vez es el momento, tal vez soy yo ahogándome en una documentación escasa y no pudiendo entender el concepto de actualización en Mongoose :)
Aquí está el trato:
Tengo un esquema y modelo de contacto (propiedades acortadas):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var mongooseTypes = require("mongoose-types"),
useTimestamps = mongooseTypes.useTimestamps;
var ContactSchema = new Schema({
phone: {
type: String,
index: {
unique: true,
dropDups: true
}
},
status: {
type: String,
lowercase: true,
trim: true,
default: 'on'
}
});
ContactSchema.plugin(useTimestamps);
var Contact = mongoose.model('Contact', ContactSchema);
Recibo una solicitud del cliente que contiene los campos que necesito y uso mi modelo de esta manera:
mongoose.connect(connectionString);
var contact = new Contact({
phone: request.phone,
status: request.status
});
Y ahora llegamos al problema:
- Si llamo
contact.save(function(err){...})
, recibiré un error si el contacto con el mismo número de teléfono ya existe (como se esperaba, único) - No puedo llamar
update()
al contacto, ya que ese método no existe en un documento - Si llamo actualización en el modelo:
Contact.update({phone:request.phone}, contact, {upsert: true}, function(err{...})
entro en un bucle infinito de algún tipo, ya que la implementación de la actualización Mongoose claramente no quiere un objeto como segundo parámetro. - Si hago lo mismo, pero en el segundo parámetro que pasar un array asociativo de las propiedades de la solicitud
{status: request.status, phone: request.phone ...}
funciona - pero luego no tengo ninguna referencia al contacto específico y no puede encontrar suscreatedAt
yupdatedAt
propiedades.
Entonces, en resumen, después de todo lo que intenté: dado un documento contact
, ¿cómo lo actualizo si existe o lo agrego si no existe?
Gracias por tu tiempo.
javascript
mongodb
node.js
mongoose
Travelling Tech Guy
fuente
fuente
pre
parasave
?Respuestas:
Mongoose ahora admite esto de forma nativa con findOneAndUpdate (llama a MongoDB findAndModify ).
La opción upsert = true crea el objeto si no existe. Por defecto es falso .
En versiones anteriores, Mongoose no admite estos ganchos con este método:
fuente
Acabo de quemar unas 3 horas sólidas tratando de resolver el mismo problema. Específicamente, quería "reemplazar" todo el documento si existe, o insertarlo de otra manera. Aquí está la solución:
Creé un problema en la página del proyecto Mongoose solicitando que se agregue información sobre esto a los documentos.
fuente
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
yMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, fn);
Estabas cerca con
pero su segundo parámetro debe ser un objeto con un operador de modificación, por ejemplo
fuente
{$set: ... }
parte aquí, ya que es mi forma automática de mi lecturaBueno, esperé lo suficiente y no obtuve respuesta. Finalmente abandoné todo el enfoque de actualización / actualización y seguí con:
¿Funciona? Sí. ¿Estoy contento con esto? Probablemente no. 2 llamadas DB en lugar de una.
Esperemos que una futura implementación de Mongoose tenga una
Model.upsert
función.fuente
runValidators: true
durante una actualización: documentos de actualización (sin embargo, los validadores de actualización solo se ejecutan$set
y$unset
funcionan).upsert()
estar disponible en todos los modelos. stackoverflow.com/a/50208331/1586406Solución muy elegante que puede lograr mediante el uso de la cadena de Promesas:
fuente
(model) => { return model.save(); }
comomodel => model.save()
, y también(err) => { res.send(err); }
comoerr => res.send(err)
;)Soy el mantenedor de Mongoose. La forma más moderna de insertar un documento es usar la
Model.updateOne()
función .Si necesita el documento insertado, puede usar
Model.findOneAndUpdate()
La conclusión clave es que necesita poner las propiedades únicas en el
filter
parámetroupdateOne()
aofindOneAndUpdate()
, y las otras propiedades en elupdate
parámetro.Aquí hay un tutorial sobre la inserción de documentos con Mongoose .
fuente
Creé una cuenta StackOverflow SOLO para responder esta pregunta. Después de buscar infructuosamente las redes, escribí algo yo mismo. Así es como lo hice para que se pueda aplicar a cualquier modelo de mangosta. Importe esta función o agréguela directamente a su código donde está realizando la actualización.
Luego, para insertar un documento de mangosta, haga lo siguiente:
Esta solución puede requerir 2 llamadas de base de datos, sin embargo, usted obtiene el beneficio de
Solo recuerde que el objeto de destino siempre anulará la fuente, incluso si la fuente tiene un valor existente
Además, para las matrices, si el objeto existente tiene una matriz más larga que la que lo reemplaza, los valores al final de la matriz anterior permanecerán. Una manera fácil de aumentar la matriz completa es configurar la matriz antigua para que sea una matriz vacía antes de la matriz, si eso es lo que tiene la intención de hacer.
ACTUALIZACIÓN - 16/01/2016 Agregué una condición adicional porque si hay una matriz de valores primitivos, Mongoose no se da cuenta de que la matriz se actualiza sin usar la función "set".
fuente
if(_.isObject(value) && _.keys(value).length !== 0) {
la condición de guardia para detener el desbordamiento de la pila. Lodash 4+ aquí, parece convertir valores no objeto en objetos en lakeys
llamada, por lo que la protección recursiva siempre fue cierta. Tal vez hay una mejor manera, pero sus casi trabajando para mí ahora ...Necesitaba actualizar / insertar un documento en una colección, lo que hice fue crear un nuevo objeto literal como este:
compuesto de datos que obtengo de otro lugar de mi base de datos y luego llamo actualización en el Modelo
Este es el resultado que obtengo después de ejecutar el script por primera vez:
Y esta es la salida cuando ejecuto el script por segunda vez:
Estoy usando la versión 3.6.16 de mangosta
fuente
Aquí hay un mejor enfoque para resolver el método de actualización en mangosta, puede consultar Scotch.io para obtener más detalles. ¡Esto definitivamente funcionó para mí!
fuente
Hay un error introducido en 2.6, y afecta a 2.7 también
El upsert solía funcionar correctamente en 2.4
https://groups.google.com/forum/#!topic/mongodb-user/UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843
Echa un vistazo, contiene información importante
ACTUALIZADO:
No significa que upsert no funcione. Aquí hay un buen ejemplo de cómo usarlo:
fuente
Simplemente puede actualizar el registro con esto y obtener los datos actualizados en respuesta
fuente
Esto funcionó para mí.
fuente
Aquí está la forma más sencilla de crear / actualizar al mismo tiempo que llama al middleware y los validadores.
fuente
Para cualquiera que llegue aquí y siga buscando una buena solución para la "inserción" con soporte de ganchos, esto es lo que he probado y estoy trabajando. Todavía requiere 2 llamadas a base de datos, pero es mucho más estable que cualquier cosa que haya probado en una sola llamada.
fuente
Si hay generadores disponibles, se vuelve aún más fácil:
fuente
Ninguna otra solución funcionó para mí. Estoy usando una solicitud de publicación y actualizando datos si se encuentra, insértela, también _id se envía con el cuerpo de la solicitud que debe eliminarse.
fuente
fuente
fuente
Después de la respuesta de Travelling Tech Guy , que ya es increíble, podemos crear un complemento y adjuntarlo a la mangosta una vez que lo inicializamos para que
.upsert()
esté disponible en todos los modelos.plugins.js
db.js
Entonces puedes hacer algo como
User.upsert({ _id: 1 }, { foo: 'bar' })
oYouModel.upsert({ bar: 'foo' }, { value: 1 })
cuando quieras.fuente
Acabo de regresar a este problema después de un tiempo y decidí publicar un complemento basado en la respuesta de Aaron Mast.
https://www.npmjs.com/package/mongoose-recursive-upsert
Úselo como un complemento de mangosta. Establece un método estático que fusionará recursivamente el objeto pasado.
fuente
Este coffeescript funciona para mí con Node: el truco es que el _id se despoja de su contenedor ObjectID cuando se envía y devuelve desde el cliente, por lo que debe reemplazarse para las actualizaciones (cuando no se proporciona _id, guardar volverá a insertarse y agregarse uno).
fuente
para construir sobre lo que Martin Kuzdowicz publicó anteriormente. Utilizo lo siguiente para hacer una actualización usando mangosta y una fusión profunda de objetos json. Junto con la función model.save () en mongoose, esto permite que la mangosta realice una validación completa, incluso una que se base en otros valores en el json. requiere el paquete deepmerge https://www.npmjs.com/package/deepmerge . Pero ese es un paquete muy ligero.
fuente
req.body
como está, antes de probar la inyección NoSQL (ver owasp.org/index.php/Testing_for_NoSQL_injection ).Después de leer las publicaciones anteriores, decidí usar este código:
Si r es nulo, creamos un nuevo elemento. De lo contrario, use upsert en la actualización porque la actualización no crea un nuevo elemento.
fuente