Проблема с использованием $ inc экспресс-маршрута с mongodb - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь вычесть значение из моего количества в моей базе данных.Я не получаю никаких ошибок, но это не вычитает значения.Я могу запустить это в оболочке Монго, и это работает, поэтому я не уверен, что мне здесь не хватает.

router.post("/item/:id", middleware.isLoggedIn, (req, res) => {
  Item.findById(req.params.id, (err, item) => {
    if (err) {
      console.log(err);
    }
    var soldItem = {
      id: item._id,
      item: item.name,
      askPrice: item.price
    };
    var soldPrice = req.body.soldPrice;
    var soldQuantity = req.body.soldQuantity;
    var itemSold = {
      soldItem: soldItem,
      soldPrice: soldPrice,
      soldQuantity: soldQuantity
    };
    SoldItem.create(itemSold, (err, sold) => {
      if (err) {
        console.log(err);
      } else {
        item.solditems = item.solditems || []; // if solditems undefined set to empty array
        item.solditems.push(sold);
        item.save().then(() => {
          item.udpdate({
            $inc: { quantity: parseInt(soldQuantity) * -1 }
          });
        });

        req.flash("success", "Item Sold");
        res.redirect("/products");
      }
    });
  });
});

Есть идеи?

1 Ответ

0 голосов
/ 11 мая 2018

Пара проблем с кодом здесь, но насколько я могу понять, что вы действительно хотите сделать, это:

// note that "async" is here because inner methods use "await"
router.post("/item/:id", middleware.isLoggedIn, async (req, res) => {

  try {
    let item = await Item.findById(req.params.id);

    // Do casting manually because you really want to
    let soldPrice = parseFloat(req.body.soldPrice);
    let soldQuantity = parseInt(req.body.soldQuantity);

    let soldItem = {
      id: item._id,
      item: item.name,
      askPrice: item.price
    };

    // create the sold item
    let soldItem = await SoldItem.create({
      soldItem,
      soldPrice,
      soldQuantity
    });

    // update the item
    await item.update({ "$inc": { "quantity": (soldQuantity * -1) } });

    // Then respond
    req.flash("success", "Item Sold");
    res.redirect("/products");
  } catch(e) {
    console.log("err", err.stack);
   // really should send the error on res here as well
  }
})

Или, если у вас на самом деле нет поддержки async/await в вашей версии узла, то с простыми обещаниями:

router.post("/item/:id", middleware.isLoggedIn, (req, res) => {

  // Do casting manually because you really want to
  let soldPrice = parseFloat(req.body.soldPrice);
  let soldQuantity = parseInt(req.body.soldQuantity);

  Item.findById(req.params.id).then(item =>
    SoldItem.create({
      soldItem: {
        id: item._id,
        item: item.name,
        askPrice: item.price
      },
      soldPrice,
      soldQuantity
    })
    .then(() => item.update({ "$inc": { "quantity": (soldQuantity * -1) }));
  }).then(() => {
    // Then respond
    req.flash("success", "Item Sold");
    res.redirect("/products");
  })
  .catch(e => {
    console.log("err", err.stack);
    // really should send the error on res here as well
  });
})

Таким образом, две «основные» проблемы в коде заключаются в том, что значение в req.body.soldQuantity на самом деле является «строкой». Когда вы отправляете такие значения через что-то вроде SoldItem.create(), тогда mongoose использует «схему» для приведения значений во все, что определено в схеме. В вашем случае это будет Number.

JavaScript примет «разумное предположение» с более поздним оператором soldQuantity *-1 и «cast» для вас, но на самом деле вы должны знать о таких вещах и просто делать преобразование типов в коде «явно», а не полагаться на неявное приведение.

Следующей проблемой был вызов update(). У мангусты есть «две формы»: Model.update() и Document.update(). Первый применяет условие «запрос», как в:

await Model.update({ "_id": 1 },{ "$inc": { "rounds": 1 } })`

Версия Document или «экземпляр» работает с «уже извлеченным» документом и имеет другой синтаксис:

let document = await Model.findById(1);
await document.update({ "$inc": { "rounds": 1 } });

Так как вы уже сделали Item.findById(), то возвращенный «документ» используется для этой формы update() способом, который в основном «подразумевает»:

await Item.update(
  { "_id": item._id },       // this is implied from the "instance"
  { "$inc": { "quantity": (soldQuantity * -1) } }
);

Но, конечно, написано в «более короткой» форме «без запроса», как показано в коде.

Остальное действительно сводится к неправильному пониманию сочетания Обещаний и обработки «обратного вызова» и цели ключевых слов async/await и того, как они переводятся в стандартную обработку обещаний. Но приведенный код должен исправить эти заблуждения, теперь у вас есть пример для подражания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...