C'est peut-être le moment, c'est peut-être moi qui me noie dans une documentation clairsemée et je ne peux pas me concentrer sur le concept de la mise à jour dans Mongoose :)
Voici l'affaire:
J'ai un schéma et un modèle de contact (propriétés raccourcies):
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);
Je reçois une demande du client, contenant les champs dont j'ai besoin et utilise ainsi mon modèle:
mongoose.connect(connectionString);
var contact = new Contact({
phone: request.phone,
status: request.status
});
Et maintenant nous arrivons au problème:
- Si j'appelle,
contact.save(function(err){...})
je recevrai une erreur si le contact avec le même numéro de téléphone existe déjà (comme prévu - unique) - Je ne peux pas faire appel
update()
au contact, car cette méthode n'existe pas sur un document - Si j'appelle mise à jour sur le modèle:
Contact.update({phone:request.phone}, contact, {upsert: true}, function(err{...})
j'entre dans une boucle infinie de certaines sortes, car l'implémentation de la mise à jour Mongoose ne veut clairement pas un objet comme deuxième paramètre. - Si je fais de même, mais dans le deuxième paramètre, je passe un tableau associatif des propriétés de la demande,
{status: request.status, phone: request.phone ...}
cela fonctionne - mais alors je n'ai aucune référence au contact spécifique et ne peux pas trouver ses propriétéscreatedAt
etupdatedAt
.
Donc, le résultat, après tout, j'ai essayé: étant donné un document contact
, comment puis-je le mettre à jour s'il existe, ou l'ajouter s'il ne l'est pas?
Merci pour votre temps.
javascript
mongodb
node.js
mongoose
Voyager Tech Guy
la source
la source
pre
poursave
?Réponses:
Mongoose prend désormais en charge cela nativement avec findOneAndUpdate (appelle MongoDB findAndModify ).
L'option upsert = true crée l'objet s'il n'existe pas. par défaut à false .
Dans les anciennes versions, Mongoose ne prend pas en charge ces crochets avec cette méthode:
la source
Je viens de brûler un solide 3 heures en essayant de résoudre le même problème. Plus précisément, je voulais "remplacer" le document entier s'il existe, ou l'insérer autrement. Voici la solution:
J'ai créé un problème sur la page du projet Mongoose demandant que des informations à ce sujet soient ajoutées aux documents.
la source
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
etMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, fn);
Tu étais proche avec
mais votre deuxième paramètre doit être un objet avec un opérateur de modification par exemple
la source
{$set: ... }
partie ici comme forme automatique de ma lectureEh bien, j'ai attendu assez longtemps et aucune réponse. A finalement renoncé à toute l'approche de mise à jour / upsert et est allé avec:
Est-ce que ça marche? Oui. Suis-je content de ça? Probablement pas. 2 appels DB au lieu d'un.
Espérons qu'une future implémentation de Mongoose proposera une
Model.upsert
fonction.la source
runValidators: true
lors d'une mise à jour: mise à jour des documents (cependant, les validateurs de mise à jour ne fonctionnent que sur$set
et les$unset
opérations).upsert()
être disponible sur tous les modèles. stackoverflow.com/a/50208331/1586406Solution très élégante que vous pouvez obtenir en utilisant la chaîne de promesses:
la source
(model) => { return model.save(); }
tant quemodel => model.save()
, et aussi en(err) => { res.send(err); }
tant queerr => res.send(err)
;)Je suis le mainteneur de Mongoose. La façon la plus moderne de mettre un document à jour est d'utiliser la
Model.updateOne()
fonction .Si vous avez besoin du document inversé, vous pouvez utiliser
Model.findOneAndUpdate()
Le point clé à retenir est que vous devez mettre les propriétés uniques dans le
filter
paramètre surupdateOne()
oufindOneAndUpdate()
, et les autres propriétés dans leupdate
paramètre.Voici un tutoriel sur la mise à jour de documents avec Mongoose .
la source
J'ai créé un compte StackOverflow JUSTE pour répondre à cette question. Après avoir vainement recherché les interwebs, j'ai juste écrit quelque chose moi-même. C'est ainsi que je l'ai fait pour qu'il puisse être appliqué à n'importe quel modèle de mangouste. Importez cette fonction ou ajoutez-la directement dans votre code où vous effectuez la mise à jour.
Ensuite, pour insérer un document mangouste, procédez comme suit,
Cette solution peut nécessiter 2 appels DB, mais vous bénéficiez de:
N'oubliez pas que l'objet de destination remplacera toujours la source même si la source a une valeur existante
De plus, pour les tableaux, si l'objet existant a un tableau plus long que celui qui le remplace, les valeurs à la fin de l'ancien tableau resteront. Un moyen simple de mettre le tableau entier à l'envers consiste à définir l'ancien tableau comme un tableau vide avant le upsert si c'est ce que vous avez l'intention de faire.
MISE À JOUR - 16/01/2016 J'ai ajouté une condition supplémentaire car s'il y a un tableau de valeurs primitives, Mongoose ne se rend pas compte que le tableau est mis à jour sans utiliser la fonction "set".
la source
if(_.isObject(value) && _.keys(value).length !== 0) {
la condition de garde pour arrêter le débordement de la pile. Lodash 4+ ici, il semble convertir des valeurs non-objets en objets dans l'keys
appel, donc la garde récursive a toujours été vraie. Peut-être qu'il y a une meilleure façon, mais ça marche presque pour moi maintenant ...Je devais mettre à jour / mettre à jour un document dans une collection, ce que j'ai fait était de créer un nouvel objet littéral comme ceci:
composé de données que j'obtiens ailleurs dans ma base de données, puis appelle la mise à jour sur le modèle
c'est la sortie que j'obtiens après avoir exécuté le script pour la première fois:
Et voici la sortie lorsque j'exécute le script pour la deuxième fois:
J'utilise la version mangouste 3.6.16
la source
Voici une meilleure approche pour résoudre la méthode de mise à jour en mangouste, vous pouvez consulter Scotch.io pour plus de détails. Cela a vraiment fonctionné pour moi !!!
la source
Il y a un bogue introduit dans 2.6, et affecte aussi à 2.7
L'upsert fonctionnait correctement sur 2.4
https://groups.google.com/forum/#!topic/mongodb-user/UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843
Jetez un oeil, il contient des informations importantes
MISE À JOUR:
Cela ne signifie pas que upsert ne fonctionne pas. Voici un bel exemple de son utilisation:
la source
Vous pouvez simplement mettre à jour l'enregistrement avec cela et obtenir les données mises à jour en réponse
la source
cela a fonctionné pour moi.
la source
Voici le moyen le plus simple de créer / mettre à jour tout en appelant le middleware et les valideurs.
la source
Pour ceux qui arrivent ici, toujours à la recherche d'une bonne solution pour "upserting" avec le support des crochets, c'est ce que j'ai testé et travaillé. Il nécessite toujours 2 appels DB mais est beaucoup plus stable que tout ce que j'ai essayé en un seul appel.
la source
Si des générateurs sont disponibles, cela devient encore plus facile:
la source
Aucune autre solution n'a fonctionné pour moi. J'utilise une demande de publication et je mets à jour les données si elles sont trouvées, insérez-la également, _id est envoyé avec le corps de la demande qui doit être supprimé.
la source
la source
la source
Suite à la réponse de Traveling Tech Guy , qui est déjà génial, nous pouvons créer un plugin et l'attacher à mangouste une fois que nous l'avons initialisé afin que
.upsert()
soit disponible sur tous les modèles.plugins.js
db.js
Ensuite, vous pouvez faire quelque chose comme
User.upsert({ _id: 1 }, { foo: 'bar' })
ouYouModel.upsert({ bar: 'foo' }, { value: 1 })
quand vous le souhaitez.la source
Je viens de revenir sur ce problème après un certain temps et j'ai décidé de publier un plugin basé sur la réponse d'Aaron Mast.
https://www.npmjs.com/package/mongoose-recursive-upsert
Utilisez-le comme un plugin mangouste. Il met en place une méthode statique qui fusionnera récursivement l'objet passé.
la source
Ce coffeescript fonctionne pour moi avec Node - l'astuce est que le _id est débarrassé de son wrapper ObjectID lorsqu'il est envoyé et retourné par le client et donc cela doit être remplacé pour les mises à jour (quand aucun _id n'est fourni, save reviendra pour insérer et ajouter une).
la source
pour s'appuyer sur ce que Martin Kuzdowicz a publié ci-dessus. J'utilise ce qui suit pour faire une mise à jour à l'aide de mangouste et une fusion profonde des objets json. Avec la fonction model.save () dans mangouste, cela permet à mangouste de faire une validation complète même en se basant sur d'autres valeurs dans le json. il nécessite le package deepmerge https://www.npmjs.com/package/deepmerge . Mais c'est un paquet très léger.
la source
req.body
tel quel , avant de tester l' injection NoSQL (voir owasp.org/index.php/Testing_for_NoSQL_injection ).Après avoir lu les articles ci-dessus, j'ai décidé d'utiliser ce code:
si r est nul, nous créons un nouvel élément. Sinon, utilisez upsert dans la mise à jour car la mise à jour ne crée pas de nouvel élément.
la source