web-dev-qa-db-fra.com

Mongoose - Crée un document s'il n'existe pas, sinon, met à jour - renvoie le document dans les deux cas

Je cherche un moyen de reformuler une partie de mon code pour qu'il soit plus court et plus simple, mais je ne connais pas très bien Mongoose et je ne sais pas comment procéder.

J'essaie de vérifier l'existence d'un document dans une collection et, s'il n'existe pas, de le créer. S'il existe, je dois le mettre à jour. Dans les deux cas, je dois ensuite accéder au contenu du document.

Ce que j’ai réussi à faire jusqu’à présent, c’est d’interroger la collection sur un document spécifique et, si ce n’est pas trouvé, de créer un nouveau document. S'il est trouvé, je le mets à jour (en utilisant actuellement les dates comme données factices pour cela). À partir de là, je peux accéder au document trouvé de mon opération initiale find ou au document nouvellement enregistré. Cela fonctionne, mais il doit exister un meilleur moyen d'accomplir ce que je recherche après.

Voici mon code de travail, sans suppléments distrayants.

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

J'ai examiné findOneAndUpdate et d'autres méthodes associées, mais je ne sais pas si elles conviennent à mon cas d'utilisation ou si je comprends comment les utiliser correctement. Est-ce que quelqu'un peut-il me montrer la bonne direction?

(Probablement) Questions connexes:


Modifier

Je ne suis pas tombé sur la question qui m’a été posée lors de mes recherches, mais après avoir examiné les réponses, j’ai trouvé ceci. À mon avis, c'est certainement plus joli et cela fonctionne. Donc, à moins que je ne fasse quelque chose de mal, je pense que ma question pourra probablement être close.

J'apprécierais toute contribution supplémentaire sur ma solution.

// 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;
            }
        });
    }
});
47
Connor

Vous recherchez le paramètre d'option new. L'option new renvoie le document nouvellement créé (si un nouveau document est créé). Utilisez-le comme ceci:

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

Puisque upsert crée un document s'il ne trouve pas de document, vous n'avez pas besoin de créer un autre manuellement.

86
user2441535

Puisque vous souhaitez refactoriser des parties de votre code pour les rendre plus simples et plus courtes,

  1. Utilisez async / await
  2. Utilisez .findOneAndUpdate() comme suggéré dans ce réponse

let query = { /* query */ };
let update = {expire: new Date()};
let options = {upsert: true, new: true, setDefaultsOnInsert: true};
let model = await Model.findOneAndUpdate(query, update, options);
5
Jossef Harush
///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)
}
0
Rahul Sadaphal