Vielleicht ist es an der Zeit, vielleicht ertrinke ich in spärlicher Dokumentation und bin nicht in der Lage, mich mit dem Konzept der Aktualisierung in Mongoose zu beschäftigen :)
Das ist der Deal:
Ich habe ein Kontaktschema und ein Modell (verkürzte Eigenschaften):
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);
Ich erhalte vom Kunden eine Anfrage mit den Feldern, die ich benötige, und verwende mein Modell folgendermaßen:
mongoose.connect(connectionString);
var contact = new Contact({
phone: request.phone,
status: request.status
});
Und jetzt erreichen wir das Problem:
- Wenn ich
contact.save(function(err){...})
anrufe, erhalte ich eine Fehlermeldung, wenn der Kontakt mit derselben Telefonnummer bereits vorhanden ist (wie erwartet - eindeutig). - Ich kann keinen
update()
Kontakt anrufen , da diese Methode in einem Dokument nicht vorhanden ist - Wenn ich update für das Modell aufrufe:
Contact.update({phone:request.phone}, contact, {upsert: true}, function(err{...})
Ich gerate in eine Endlosschleife, da die Implementierung des Mongoose-Updates eindeutig kein Objekt als zweiten Parameter haben möchte. - Wenn ich dasselbe mache, aber im zweiten Parameter ein assoziatives Array der Anforderungseigenschaften übergebe
{status: request.status, phone: request.phone ...}
, funktioniert es - aber dann habe ich keinen Verweis auf den spezifischen Kontakt und kann seinecreatedAt
undupdatedAt
Eigenschaften nicht herausfinden .
Nach dem Fazit habe ich also versucht: contact
Wenn ich ein Dokument gegeben habe , wie aktualisiere ich es, wenn es existiert, oder füge es hinzu, wenn es nicht existiert?
Vielen Dank für Ihre Zeit.
javascript
mongodb
node.js
mongoose
Travelling Tech Guy
quelle
quelle
pre
fürsave
?Antworten:
Mongoose unterstützt dies jetzt nativ mit findOneAndUpdate (ruft MongoDB findAndModify auf ).
Die Option upsert = true erstellt das Objekt, wenn es nicht vorhanden ist. Der Standardwert ist false .
In älteren Versionen unterstützt Mongoose diese Hooks mit dieser Methode nicht:
quelle
Ich habe gerade 3 Stunden lang gebrannt, um das gleiche Problem zu lösen. Insbesondere wollte ich das gesamte Dokument "ersetzen", falls vorhanden, oder es anderweitig einfügen. Hier ist die Lösung:
Ich habe auf der Mongoose-Projektseite ein Problem erstellt, bei dem angefordert wurde, dass Informationen dazu in die Dokumente aufgenommen werden.
quelle
MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
undMyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, fn);
Du warst nah dran
Ihr zweiter Parameter sollte jedoch beispielsweise ein Objekt mit einem Änderungsoperator sein
quelle
{$set: ... }
Teil hier als seine automatische Form meiner LektüreNun, ich habe lange genug gewartet und keine Antwort erhalten. Schließlich gab der gesamte Update / Upsert-Ansatz auf und ging mit:
Funktioniert es? Ja. Bin ich damit zufrieden? Wahrscheinlich nicht. 2 DB-Aufrufe statt eines.
Hoffentlich würde eine zukünftige Implementierung von Mongoose eine
Model.upsert
Funktion haben.quelle
runValidators: true
während eines Updates manuell übergeben : Update-Dokumente (Update-Validatoren werden jedoch nur ausgeführt$set
und$unset
Vorgänge ausgeführt).upsert()
für alle Modelle verfügbar sein müssen. stackoverflow.com/a/50208331/1586406Sehr elegante Lösung, die Sie mit der Kette von Versprechen erreichen können:
quelle
(model) => { return model.save(); }
alsmodel => model.save()
und auch(err) => { res.send(err); }
als umzuschreibenerr => res.send(err)
;)Ich bin der Betreuer von Mongoose. Die modernere Möglichkeit, ein Dokument zu aktualisieren, besteht darin, die
Model.updateOne()
Funktion zu verwenden .Wenn Sie das aktualisierte Dokument benötigen, können Sie es verwenden
Model.findOneAndUpdate()
Der Schlüssel zum Erfolg ist, dass Sie die eindeutigen Eigenschaften des
filter
Parameters inupdateOne()
oderfindOneAndUpdate()
und die anderen Eigenschaften desupdate
Parameters einfügen müssen.Hier ist ein Tutorial zum Upserting von Dokumenten mit Mongoose .
quelle
Ich habe NUR ein StackOverflow-Konto erstellt, um diese Frage zu beantworten. Nachdem ich die Interwebs erfolglos durchsucht hatte, schrieb ich selbst etwas. So habe ich es gemacht, damit es auf jedes Mungomodell angewendet werden kann. Importieren Sie diese Funktion entweder oder fügen Sie sie direkt in Ihren Code ein, in dem Sie die Aktualisierung durchführen.
Um ein Mungo-Dokument zu verbessern, gehen Sie wie folgt vor:
Diese Lösung erfordert möglicherweise 2 DB-Aufrufe, Sie profitieren jedoch von:
Denken Sie daran, dass das Zielobjekt die Quelle immer überschreibt, auch wenn die Quelle einen vorhandenen Wert hat
Wenn für Arrays das vorhandene Objekt ein längeres Array hat als das, das es ersetzt, bleiben die Werte am Ende des alten Arrays erhalten. Eine einfache Möglichkeit, das gesamte Array zu aktualisieren, besteht darin, das alte Array vor dem Upsert als leeres Array festzulegen, wenn Sie dies beabsichtigen.
UPDATE - 16.01.2016 Ich habe eine zusätzliche Bedingung hinzugefügt, denn wenn es ein Array primitiver Werte gibt, erkennt Mongoose nicht, dass das Array ohne Verwendung der Funktion "set" aktualisiert wird.
quelle
if(_.isObject(value) && _.keys(value).length !== 0) {
, um den Stapelüberlauf zu stoppen. Lodash 4+ hier scheint es, Nicht-Objektwerte in Objekte imkeys
Aufruf umzuwandeln , so dass rekursiver Schutz immer wahr war. Vielleicht gibt es einen besseren Weg, aber es funktioniert jetzt fast für mich ...Ich musste ein Dokument aktualisieren / in eine Sammlung einfügen. Ich habe ein neues Objektliteral wie das folgende erstellt:
Besteht aus Daten, die ich von einer anderen Stelle in meiner Datenbank erhalte und dann die Aktualisierung des Modells aufrufe
Dies ist die Ausgabe, die ich bekomme, nachdem ich das Skript zum ersten Mal ausgeführt habe:
Und dies ist die Ausgabe, wenn ich das Skript zum zweiten Mal ausführe:
Ich benutze Mungo Version 3.6.16
quelle
Hier ist ein besserer Ansatz zur Lösung der Aktualisierungsmethode in Mungo. Weitere Informationen finden Sie in Scotch.io . Das hat definitiv bei mir funktioniert !!!
quelle
In 2.6 wurde ein Fehler eingeführt, der sich auch auf 2.7 auswirkt
Der Upsert funktionierte in 2.4 korrekt
https://groups.google.com/forum/#!topic/mongodb-user/UcKvx4p4hnY https://jira.mongodb.org/browse/SERVER-13843
Schauen Sie sich das an, es enthält einige wichtige Informationen
AKTUALISIERT:
Es bedeutet nicht, dass Upsert nicht funktioniert. Hier ist ein schönes Beispiel für die Verwendung:
quelle
Sie können den Datensatz einfach damit aktualisieren und die aktualisierten Daten als Antwort erhalten
quelle
das hat bei mir funktioniert.
quelle
Hier ist der einfachste Weg zum Erstellen / Aktualisieren, während gleichzeitig die Middleware und die Validatoren aufgerufen werden.
quelle
Für alle, die hier ankommen und noch nach einer guten Lösung für das "Upserting" mit Hakenunterstützung suchen, ist dies das, was ich getestet habe und arbeite. Es erfordert immer noch 2 DB-Aufrufe, ist aber viel stabiler als alles, was ich in einem einzelnen Aufruf versucht habe.
quelle
Wenn Generatoren verfügbar sind, wird es noch einfacher:
quelle
Bei mir hat keine andere Lösung funktioniert. Ich verwende eine Post-Anfrage und aktualisiere Daten, wenn sie gefunden werden. Andernfalls füge sie ein. Außerdem wird _id mit dem Anfragetext gesendet, der entfernt werden muss.
quelle
quelle
quelle
Nach der Antwort von Travelling Tech Guy , die bereits großartig ist, können wir ein Plugin erstellen und es an Mungo anhängen, sobald wir es so initialisiert haben
.upsert()
damit es für alle Modelle verfügbar ist.plugins.js
db.js
Dann können Sie so etwas tun
User.upsert({ _id: 1 }, { foo: 'bar' })
oderYouModel.upsert({ bar: 'foo' }, { value: 1 })
wann immer Sie wollen.quelle
Ich bin gerade nach einer Weile auf dieses Problem zurückgekommen und habe beschlossen, ein Plugin zu veröffentlichen, das auf der Antwort von Aaron Mast basiert.
https://www.npmjs.com/package/mongoose-recursive-upsert
Verwenden Sie es als Mungo-Plugin. Es wird eine statische Methode eingerichtet, mit der das übergebene Objekt rekursiv zusammengeführt wird.
quelle
Dieses Coffeescript funktioniert für mich mit Node - der Trick besteht darin, dass die _id beim Senden und Zurückgeben vom Client vom ObjectID-Wrapper befreit wird und daher für Updates ersetzt werden muss (wenn keine _id angegeben ist, wird save zum Einfügen und Hinzufügen zurückgesetzt einer).
quelle
um auf dem aufzubauen, was Martin Kuzdowicz oben gepostet hat. Ich verwende das Folgende, um ein Update mit Mungo und einer tiefen Zusammenführung von JSON-Objekten durchzuführen. Zusammen mit der Funktion model.save () in mongoose ermöglicht dies mongoose eine vollständige Validierung, selbst wenn diese auf anderen Werten im json beruht. Es erfordert das Deepmerge-Paket https://www.npmjs.com/package/deepmerge . Aber das ist ein sehr leichtes Paket.
quelle
req.body
vor dem Testen auf NoSQL-Injection davor warnen , wie sie ist zu verwenden (siehe owasp.org/index.php/Testing_for_NoSQL_injection ).Nachdem ich die obigen Beiträge gelesen hatte, entschied ich mich, diesen Code zu verwenden:
Wenn r null ist, erstellen wir ein neues Element. Verwenden Sie andernfalls upsert in update, da durch update kein neues Element erstellt wird.
quelle