2 votes

mangouste @set et $unset conditionnels

Dans mon projet, je veux autoriser des champs optionnels dans un document, mais je ne veux pas enregistrer de valeurs nulles, c'est-à-dire que je veux supprimer tout champ contenant des valeurs nulles.

les valeurs peuvent être modifiées en cours d'exécution.

J'ai trouvé comment rendre un champ nul si l'utilisateur n'a pas envoyé de données pour le mettre à jour (tous les champs pour lesquels l'utilisateur a envoyé des valeurs vides doivent être supprimés).

Si l'utilisateur envoie son prénom et son nom sous forme de chaîne vide dans le formulaire, je veux les supprimer.

await Employee.findOneAndUpdate({ _id: employee._id },
     {$set: {firstName: null, lastName: null, ...req.body.newEmployee}}, { new: true, upsert: false });

J'ai essayé d'ajouter une option $unset mais j'ai obtenu une erreur

MongoError: Updating the path 'firstName' would create a conflict at 'firstName'

J'ai pensé à le supprimer après la mise à jour (comme une deuxième commande) mais je ne trouve pas de moyen de connaître/obtenir tous les champs null de l'employé, et je ne peux pas obtenir de valeurs fixes à vérifier parce qu'il y a beaucoup de combinaisons pour les valeurs null/non null, surtout s'il y a plus de champs dans le futur. Par exemple, je ne peux pas dire si (FN : null, LN : null ou FN : "johny", LN : null etc )

3voto

srinivas y Points 205

Mise à jour : Si vous avez besoin de conserver certains champs tels quels dans le document existant, essayez ceci. Avec ce nouveau code, seuls les champs entrant dans la requête seront mis à jour ou supprimés, sans modifier les autres champs existants dans le document :

Votre code node.js :

let removeObj = {}
Object.entries(req.body).forEach(([key, val]) => {
    if (!val) { delete req[body][key]; removeObj[key] = '' };
})

let bulkArr = []
if (req.body) bulkArr.push({
    updateOne: {
        "filter": { "_id": ObjectId("5e02da86400289966e8ffa4f") },
        "update": { $set: req.body }
    }
})
if (Object.entries(removeObj).length > 0 && removeObj.constructor === Object) bulkArr.push({
    updateOne: {
        "filter": { "_id": ObjectId("5e02da86400289966e8ffa4f") },
        "update": { $unset: removeObj }
    }
})

// For mongoDB4.2 removeObj has to be an array of strings(field names)
let removeObj = []
Object.entries(req.body).forEach(([key, val]) => {
    if (!val) { delete req[body][key]; removeObj.push(key) };
})
// After this, Similar to above you need to write code to exclude empty removeObj for 4.2 as well.

Requête : : Sur la version de MongoDB >= 3.2 à < 4.2 .bulkWrite() :

db.yourCollectionName.bulkWrite(bulkArr) 

Requête : : A partir de la version 4.2 de MongoDB .updateOne accepte le pipeline d'agrégation :

db.yourCollectionName.updateOne(
    { "_id": ObjectId("5e02da86400289966e8ffa4f") },
    [
        {
            $set: req.body
        },
        { $unset: removeObj }
    ]
)

Ancienne réponse : Vous devez essayer .findOneAndReplace() Si vous souhaitez que l'ensemble du document soit remplacé :

db.yourCollectionName.findOneAndReplace({_id: ObjectId("5e02da86400289966e8ffa4f")},inputObj, {returnNewDocument:true})

Votre collection :

{
    "_id" : ObjectId("5e02da86400289966e8ffa4f"),
    "firstName" : "noName",
    "lastName": 'noName',
    "value" : 1.0,
    "empDept": 'general',
    "password":'something'
}

L'objet de votre demande se présente comme suit :

req.body = {
    firstName: 'firstName',
    lastName: null,
    value : 1.0,
    empDept: ''
}

votre code node.js (Supprime toutes les valeurs falsy ("", 0, false, null, undefined )) :

let inputObj = Object.entries(req.body).reduce((a,[k,v]) => (v ? {...a, [k]:v} : a), {})

votre collection après l'opération :

{
    "_id" : ObjectId("5e02da86400289966e8ffa4f"),
    "firstName" : "firstName",
    "value" : 1.0,
}

votre collection après l'opération, conformément à la réponse mise à jour :

{
    "_id" : ObjectId("5e02da86400289966e8ffa4f"),
    "firstName" : "firstName",
    "value" : 1.0,
    "password":'something'
}

0 votes

Je voudrais savoir s'il est possible de conserver certains champs. J'ai un champ de mot de passe avec lequel je n'interagis que lors de l'inscription et de la connexion, et je veux le conserver.

0 votes

@guy : quelle est votre version de MongoDB ?

0 votes

MongoDb 4.0.13, mongoose 5.7.14

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X