Mungo - Dokument erstellen, falls nicht vorhanden. Andernfalls wird das Dokument in beiden Fällen aktualisiert und zurückgegeben

71

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 das Vorhandensein eines Dokuments zu überprüfen und es zu erstellen, falls es nicht vorhanden ist. Wenn es existiert, muss ich es aktualisieren. In beiden Fällen muss ich anschließend auf den Inhalt des Dokuments zugreifen.

Was ich bisher geschafft habe, ist, die Sammlung nach einem bestimmten Dokument abzufragen und, falls es nicht gefunden wird, ein neues Dokument zu erstellen. Wenn es gefunden wird, aktualisiere ich es (derzeit werden Daten als Dummy-Daten verwendet). Von dort aus kann ich entweder auf das gefundene Dokument aus meiner ersten findOperation oder auf das neu gespeicherte Dokument zugreifen, und dies funktioniert, aber es muss einen besseren Weg geben, um das zu erreichen, wonach ich suche.

Hier ist mein Arbeitscode 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 mich findOneAndUpdatemit anderen verwandten Methoden befasst, bin mir aber 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:


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 darauf gekommen. Meiner Meinung nach ist es sicherlich hübscher und es funktioniert. Wenn ich also nichts Schreckliches falsch mache, denke ich, dass meine Frage wahrscheinlich geschlossen werden kann.

Ich würde mich über zusätzliche 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;
            }
        });
    }
});
Connor
quelle
1
Que: Mongoose.js: Wie implementiere ich create oder update? Antwort
Alok Deshwal
Ich fühle mich jetzt ziemlich dumm, ehrlich. Ich habe diese Frage bei der Suche nicht gefunden, aber im Nachhinein scheint die Antwort ziemlich einfach zu verstehen. Danke für die Hilfe!
Connor

Antworten:

130

Sie suchen die new Optionsparameter. Die newOption gibt das neu erstellte Dokument zurück (wenn ein neues Dokument erstellt wird). Verwenden Sie es so:

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
});

Da upsertein Dokument erstellt wird, wenn kein Dokument gefunden wird, müssen Sie kein weiteres manuell erstellen.


quelle
2
Dies scheint zu funktionieren, außer dass das neu erstellte Dokument nicht mit den in meinem Schema definierten Standardwerten gefüllt ist. Sehr verwirrend. Gibt es einen Grund, warum das so sein könnte?
Connor
2
@Connor Ja, es ist eine Standardfunktion in Mungo, obwohl es eine Option gibt, um dies zu beheben. Überprüfen Sie meine aktualisierte Antwort.
Eine seltsame kleine Eigenart, aber ich denke, die Entwickler hatten ihre Gründe. Dies ist eine ziemlich fantastische Lösung für mein Problem. Vielen Dank für Ihre Hilfe!
Connor
1
Wie identifizieren Sie in diesem Fall, welchen Statuscode gesendet wird? 200 = aktualisiert. 201 erstellt
jhonny lopez
Was passiert, wenn das Objekt, das ich aktualisieren möchte, eine Liste von IDs enthält und ich eine neue ID hinzufügen möchte? Wird dies die Liste ersetzen oder ergänzen?
Shinzou
14

Da Sie Teile Ihres Codes so umgestalten möchten, dass sie kürzer und einfacher sind,

  1. Verwenden async / await
  2. Verwenden Sie .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);
Jossef Harush
quelle
0
///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)
}
Rahul Sadaphal
quelle
-1

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);
    }
  })
});

Hongkongbboy
quelle