Mongoose – Dokument erstellen, falls nicht vorhanden, andernfalls aktualisieren – Dokument in jedem Fall zurückgeben

Lesezeit: 6 Minuten

Benutzer-Avatar
Konnor

Ich suche nach einer Möglichkeit, einen Teil meines Codes kürzer und einfacher umzugestalten, aber ich kenne Mongoose nicht sehr gut und bin mir nicht sicher, wie ich vorgehen soll.

Ich versuche, eine Sammlung auf die Existenz eines Dokuments zu überprüfen und, falls nicht vorhanden, ein Dokument zu erstellen. Wenn es existiert, muss ich es aktualisieren. In beiden Fällen muss ich danach auf den Inhalt des Dokuments zugreifen.

Bisher ist es mir gelungen, die Sammlung nach einem bestimmten Dokument abzufragen und, wenn es nicht gefunden wird, ein neues Dokument zu erstellen. Wenn es gefunden wird, aktualisiere ich es (aktuell verwende ich dafür Datumsangaben als Dummy-Daten). Von dort aus kann ich entweder auf das gefundene Dokument aus meiner Initiale zugreifen find Vorgang oder das neu gespeicherte Dokument und das funktioniert, aber es muss einen besseren Weg geben, um das zu erreichen, wonach ich suche.

Hier ist mein funktionierender Code, ohne ablenkende Extras.

var query = Model.find({
    /* query */
}).lean().limit(1);

// Find the document
query.exec(function(error, result) {
    if (error) { throw error; }
    // If the document doesn't exist
    if (!result.length) {
        // Create a new one
        var model = new Model(); //use the defaults in the schema
        model.save(function(error) {
            if (error) { throw error; }
            // do something with the document here
        });
    }
    // If the document does exist
    else {
        // Update it
        var query = { /* query */ },
            update = {},
            options = {};

        Model.update(query, update, options, function(error) {
            if (error) { throw error; }
            // do the same something with the document here
            // in this case, using result[0] from the topmost query
        });
    }
});

Ich habe nachgesehen findOneAndUpdate und andere verwandte Methoden, aber ich bin mir nicht sicher, ob sie zu meinem Anwendungsfall passen oder ob ich verstehe, wie man sie richtig verwendet. Kann mich jemand in die richtige Richtung weisen?

(Wahrscheinlich) Verwandte Fragen:

  • So überprüfen Sie, ob diese Daten während des Updates bereits in der Datenbank vorhanden sind (Mongoose und Express)
  • Mongoose.js: Wie implementiert man create oder update?
  • NodeJS + Mongo: Einfügen, wenn nicht vorhanden, sonst – aktualisieren
  • Geben Sie die aktualisierte Sammlung mit Mongoose zurück

Bearbeiten

Ich bin bei meiner Suche nicht auf die Frage gestoßen, auf die ich hingewiesen wurde, aber nachdem ich die Antworten dort überprüft habe, bin ich auf diese gekommen. Meiner Meinung nach ist es sicherlich schöner und funktioniert. Wenn ich also nichts schrecklich falsch mache, kann meine Frage wahrscheinlich geschlossen werden.

Ich würde mich über weitere Beiträge zu meiner Lösung freuen.

// Setup stuff
var query = { /* query */ },
    update = { expire: new Date() },
    options = { upsert: true };

// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
    if (!error) {
        // If the document doesn't exist
        if (!result) {
            // Create it
            result = new Model();
        }
        // Save the document
        result.save(function(error) {
            if (!error) {
                // Do something with the document
            } else {
                throw error;
            }
        });
    }
});

  • Que:Mongoose.js: Wie implementiert man create oder update? Antwort: stackoverflow.com/questions/7267102/…

    – Alok Deshwal

    23. Oktober 2015 um 15:34 Uhr

  • Ich fühle mich jetzt ziemlich dumm, ehrlich. Ich habe diese Frage bei meiner Suche nicht gefunden, aber im Nachhinein scheint die Antwort ziemlich einfach zu verstehen. Danke für die Hilfe!

    – Konnor

    23. Oktober 2015 um 16:51 Uhr

Sie suchen die new Optionsparameter. Das new Option gibt das neu erstellte Dokument zurück (wenn ein neues Dokument erstellt wird). Verwenden Sie es wie folgt:

var query = {},
    update = { expire: new Date() },
    options = { upsert: true, new: true, setDefaultsOnInsert: true };

// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
    if (error) return;

    // do something with the document
});

Seit upsert erstellt ein Dokument Wenn kein Dokument gefunden wird, müssen Sie kein weiteres Dokument manuell erstellen.

  • Dies scheint zu funktionieren, außer dass das neu erstellte Dokument nicht mit den in meinem Schema definierten Standardwerten gefüllt ist. Sehr verwirrend. Irgendein Grund, warum das sein könnte, weißt du?

    – Konnor

    1. November 2015 um 16:09 Uhr

  • @Connor Ja, es ist eine Standardfunktion in Mungo, obwohl es eine Option gibt, dies zu beheben. Überprüfen Sie meine aktualisierte Antwort.

    Benutzer2441535

    1. November 2015 um 20:39 Uhr


  • Irgendwie eine seltsame kleine Macke, aber ich nehme an, die Entwickler hatten ihre Gründe. Dies ist eine ziemlich fantastische Lösung für mein Problem, also vielen Dank für Ihre Hilfe!

    – Konnor

    4. November 2015 um 17:59 Uhr

  • Wie erkennen Sie in diesem Fall, welcher Statuscode gesendet wird? 200= aktualisiert . 201 erstellt

    – Jhonny Lopez

    18. Januar 2019 um 16:53 Uhr

  • Was ist, wenn das Objekt, das ich zu aktualisieren versuche, eine Liste mit IDs hat und ich eine neue ID hinzufügen möchte? Wird dies die Liste ersetzen oder ergänzen?

    – Shinzu

    16. Dezember 2020 um 22:43 Uhr

Da Sie Teile Ihres Codes kürzer und einfacher umgestalten möchten,

  1. Verwenden async / await
  2. Verwenden .findOneAndUpdate() wie in dieser Antwort vorgeschlagen

let query = { /* query */ };
let update = {expire: new Date()};
let options = {upsert: true, new: true, setDefaultsOnInsert: true};
let model = await Model.findOneAndUpdate(query, update, options);

  • Wenn Sie die Elemente in einem JSON mit einer API abrufen und ein Modell verwenden möchten, gehen Sie wie folgt vor: let update = JSON.parse(data);

    – Drachenfeuer

    8. Februar 2021 um 6:56 Uhr


  • Vergiss nicht, es mit try&catch abzuschließen 🙂

    – Meisterstück

    25. April 2021 um 22:39 Uhr

///This is simple example explaining findByIDAndUpdate from my code added with try catch block to catch errors
try{
const options = {
            upsert: true,
            new: true,
            setDefaultsOnInsert: true
        };
        const query = {
            $set: {
                description: req.body.description,
                title: req.body.title
            }
        };
        const survey = await Survey.findByIdAndUpdate(
            req.params.id,
            query,
            options
        ).populate("questions");
}catch(e){
console.log(e)
}

Hier ist ein Beispiel, das ich verwende. Ich muss benutzerdefinierte Antworten für UI-Updates usw. zurückgeben. Dies kann sogar noch kürzer sein. Benutzer ist

const UserScheme = mongoose.Schema({
    _id: String,
    name: String,
    city: String,
    address: String,
},{timestamps: true});

const User = mongoose.model('Users', UserScheme);


async function userUpdateAdd(data){
    var resp = '{"status": "error"}';
    if(data){
    var resp = await User.updateOne({ _id: data._id }, data).then(function(err, res){
        console.log("database.userUpdateAdd -> Update data saved in database!");
        if(err){
            var errMessage = err.matchedCount == 0 ? "User Record does not exist, will create new..." : "Record not updated";
            // If no match, create new
            if(err.matchedCount == 0){
                const create_user = new User(data);
                resp = create_user.save().then(function(){
                    console.log("database.userUpdateAdd -> Data saved to database!");
                    return '{"status":"success", "message": "New User added successfully"}';
                });
                return resp;
            }

            // Exists, return success update message
            if(err.matchedCount == 1){
                return '{"status": "success", "message" : "Update saved successfully"}';
            } else {
                return '{"status": "error", "code": "' + err.modifiedCount + '", "message": "' + errMessage + '"}';
            }
        }
        })
        .catch((error) => {
            //When there are errors We handle them here
            console.log("database.userUpdateAdd -> Error, data not saved! Server error");
            return '{"status": "error", "code": "400", "message": "Server error!"}';
        });
    }
    return resp;
}

Hier ist ein Beispiel:

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/rsvp', {useNewUrlParser: true, useUnifiedTopology: true});

const db = mongoose.connection;

db.on('error', () => {
  console.log('mongoose connection error');
});

db.once('open', () => {
  console.log('mongoose connected successfully');
});

const rsvpSchema = mongoose.Schema({
  firstName: String,
  lastName: String,
  email: String,
  guests: Number
});

const Rsvp = mongoose.model('Rsvp', rsvpSchema);


// This is the part you will need... In this example, if first and last name match, update email and guest number. Otherwise, create a new document. The key is to learn to put "upsert" as the "options" for the argument.
const findRsvpAndUpdate = (result, callback) => {

  Rsvp.findOneAndUpdate({firstName: result.firstName, lastName: result.lastName}, result, { upsert: true }, (err, results) => {
    if (err) {
      callback(err);
    } else {
      callback(null, results);
    }
  })
};


// From your server index.js file, call this...
app.post('/rsvps', (req, res) => {
  findRsvpAndUpdate(req.body, (error, result) => {
    if (error) {
      res.status(500).send(error);
    } else {
      res.status(200).send(result);
    }
  })
});

1181280cookie-checkMongoose – Dokument erstellen, falls nicht vorhanden, andernfalls aktualisieren – Dokument in jedem Fall zurückgeben

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy