4
votes

Mongoose - Comment mettre à jour de nombreux enregistrements spécifiques avec une valeur par enregistrement?

Comment puis-je mettre à jour plusieurs enregistrements en utilisant mangouste dans NodeJS - Express, chacun avec une valeur unique (les éléments n'ont pas tous la même valeur) sans causer de problème N + 1? J'ai le scénario suivant:

Produits:

[
{
 _id: "407f191e810c19729de860ea",
 title: "....",
 in_stock: 92,
 },
{
 _id: "507f1f77bcf86cd799439011",
 title: "....",
 in_stock: 95,
 },
....
]

Puis une demande de "commande" comme celle-ci:

[
 {
  item_id: "507f1f77bcf86cd799439011",
  quantity: 5
 },
 {
  item_id: "407f191e810c19729de860ea",
  quantity: 8
 },
...
]

En d'autres termes, étant donné un tableau de tuples id, quantité, je dois réduire le stock de chaque enregistrement correspondant dans la base de données. Comment cela peut-il être fait sans avoir à exécuter une requête par élément?

Dans l'exemple ci-dessus, le résultat final dans la base de données doit être:

[
{
 _id: "407f191e810c19729de860ea",
 title: "....",
 in_stock: 100,
 },
{
 _id: "507f1f77bcf86cd799439011",
 title: "....",
 in_stock: 100,
 },
....
]

p >


0 commentaires

3 Réponses :


2
votes

Eh bien, dans ce cas, vous pouvez un peu utiliser un code comme celui-ci. Mais je doute fortement que ce soit ce que vous voulez réaliser.

J'ai également essayé le même problème dans mon projet, mais je suis tombé sur le seul moyen de le faire est d'itérer par identifiant et d'exécuter uniquement différentes requêtes.

updateById(0); //call updates iteration

function updateById(i) {
if (i < order.length) {
    Products.findByIdAndUpdate({ _id: order[i]._id }, { in_stock: order[i].in_stock }, (err, data) => {
        if (!err) { updateById(i++); }
        else{throw err}
    });
}
else {
    // return 
}

}

un code comme cela devrait faire l'affaire

db.Element.update(
       { _id: { $in: ['id1', 'id2', 'id3'] } },
       { $set: { visibility : yourvisibility } }
    )


1 commentaires

Ça a du sens ... J'espérais peut-être qu'il serait possible de définir chaque élément séparément dans une seule requête ...



2
votes

Vous devrez parcourir votre tableau de commandes pour trouver l'article en stock en utilisant l'identifiant, puis vous pouvez mettre à jour le décompte des stocks, comme,

order.forEach((item) => {
  Products.findByIdandUpdate(item._id, 
    {$set: {in_stock: (in_stock - item.quantity)}}, {new:true})
    .then((updatedItem) => {
      if(!updatedItem) {
        console.log('Cannot update!');
      }
      else {
       console.log(updatedItem);
      }
 });
});


0 commentaires

1
votes

Pour ceux qui rencontrent cette question, je n'ai pas encore trouvé de solution non N + 1 à cela. Pour développer les réponses ci-dessus, la meilleure solution que j'ai trouvée est d'utiliser le module async, pour au moins éviter le code potentiellement bloquant:

itemModel.find({ // find items from ids
    '_id': itemIds
}).then(function (items) {
    if (items) {
        asyncModule.each(items,
            function (item, callback) {
                item.in_stock -= orderQuantities[item._id];
                item.save();
                callback(); // tell async that current object is done processing
            }, onCompleteFunc);
    }
}).catch(handleError);

Si quelqu'un a un commentaire ou une suggestion d'amélioration à cette solution , les commentaires sont les bienvenus.


0 commentaires