返回值延迟 - nodejs & mongoose

Delay in return value - nodejs & mongoose

提问人:Ope Afolabi 提问时间:12/27/2021 更新时间:12/27/2021 访问量:268

问:

我对 nodejs 相当陌生,我正在做一个来自 devchallenges.io (Shoppingify) 的全栈开发人员挑战。下面,我尝试根据用户单击以增加或减少项目数量来增加数量值。但是,请求的返回值与数据库中的实际值之间存在轻微的延迟。似乎该值会立即更新,这很好,但是,请求中的返回值是以前的值,而不是数据库中的当前数量值。

mongoDB 数据库

enter image description here

enter image description here

// @route    PUT api/list/item/quantity/:id
// @desc     update item quantity
// @access   Private
router.put('/item/quantity/:id', auth, async (req, res) => {
  const { action } = req.body;
  try {
    let list = await List.findOne({ user: req.user.id });

    // find current quantity
    const item = list.items.find((item) => {
      return item._id.toString() === req.params.id;
    });

    // increase quantity
    if (action === 'increase') {
      list = await List.findOneAndUpdate(
        { 'items._id': req.params.id },
        { $set: { 'items.$.quantity': item.quantity + 1 } },
        { new: true }
      );
    } else {
      // decrease quantity
      list = await List.findOneAndUpdate(
        { 'items._id': req.params.id },
        { $set: { 'items.$.quantity': item.quantity - 1 } },
        { new: true }
      );
    }

    res.json(item.quantity);
  } catch (error) {
    console.error(error.message);
    res.status(500).send('Server Error');
  }
});

node.js mongodb express 猫鼬

评论


答:

1赞 Tom Slabbaert 12/27/2021 #1

你在这里定义:item

const item = list.items.find((item) => {
      return item._id.toString() === req.params.id;
    });

此时是对象的“旧”版本,您希望在更新对象时执行相同的操作,然后才返回它。listlist

// this is the original "list" item
let item = list.items.find((item) => {
   return item._id.toString() === req.params.id;
});

...
update list
...

// now "list" is updated
item = list.items.find((item) => {
   return item._id.toString() === req.params.id;
});

我只添加两个额外的技巧来提高性能,它们是相互排斥的,因此您必须选择两者之一。

  1. 在更新查询中添加,如果我猜测该集合在字段上没有索引(如果有,这通常是一个坏主意)。这意味着当您仅使用字段进行更新时,Mongo 需要更长的时间才能找到对象。这是对两个更新的快速更改:list._iditemsitem._id
list = await List.findOneAndUpdate(
    { _id: list._id, 'items._id': req.params.id },
    { $set: { 'items.$.quantity': item.quantity - 1 } },
    { new: true }
);
  1. (我的首选选项)使用update arrayFilters选项在单个调用中执行此操作,如下所示:
const list = await List.findOneAndUpdate(
    {
        user: req.user.id,
    },
    {
        $inc: {
            'items.$[elem].quantity': action === 'increase' ? 1 : -1,
        },
    },
    {
        arrayFilters: [
            {
                'elem._id': new ObjectId(req.params.id),
            },
        ],
        new: true,
    });

const item = list.items.find((item) => {
    return item._id.toString() === req.params.id;
});

蒙戈游乐场

在我看来,现在您的路由看起来好多了,您也从 2 db 调用减少到 1。

评论

0赞 Ope Afolabi 12/28/2021
你是明星,谢谢你:)