猫鼬地图字段未通过doc.save()调用进行更新

时间:2019-01-14 00:57:26

标签: javascript node.js mongodb express mongoose

我正在尝试使用Mongoose更新mongoDB中的模型Cart。在我的购物车模型中,我有2种地图架构类型,分别称为itemsListitemsPrices。我遇到的问题很奇怪,因为当我尝试“结帐”我的购物车时,模型的其他字段将被保存和更新,例如小计,状态等,但是我对两个地图字段所做的更改却没有保持在数据库中。

我已经做的是在我调用购物车对象上的save函数之前,先验证项目是否已更改以及地图是否已修改,并验证其他字段是否实际更新。这很奇怪,因为当我尝试将商品添加到购物车时。在2个地图字段中添加一个值,它们会更新并保留在数据库中。但是,当我尝试删除它们时,它们并没有坚持删除。

我的购物车模型

let CartSchema = new mongoose.Schema({
  itemsList: {
    type: Map,
    of: Number
  },
  itemsPrices: {
    type: Map,
    of: Number
  },
  subtotal: {
    type: Number,
    default: 0
  },
  status: {
    type: String,
    enum: ['open', 'partially-completed', 'completed'],
    default: 'open'
  },
  fulfilled: {
    type: Date
  }
})

我在Express中的结帐路线

//Checks out a cart
router.put('/api/cart/:id/checkout', (req, res) => {
  CartModel.findById(req.params.id)
    .then(cart => {
      console.log(cart)
      let checkedOutCart = checkoutCart(cart)
      console.log(checkedOutCart)
      cart = checkedOutCart //also tried cart.set(checkedOutCart)
      cart.save(function(err, doc) {
        if (err) {
          return res.status(400).send(err)
        }
        res.json(doc)
      })
    })
    .catch(err => {
      console.log(err)
      return res.status(400).json(err)
    })
})

我的checkoutCart(cart)函数

function checkoutCart(cart) {
  for (const [itemId, quantity] of cart.itemsList) {
    console.log(`Trying to purchase item: ${itemId}, Quantity: ${quantity}`)
    let leftInCart = purchaseItem(itemId, quantity)
    //Not enough inventory to purchase all items
    if (leftInCart > 0) {
      //Update the quantity of the item with how much is left
      cart.itemsList.set(itemId, leftInCart)
    } else {
      //Remove the item from the prices and quantity lists
      cart.itemsList.delete(itemId)
      cart.itemsPrices.delete(itemId)
    }
  }
  //Update the carts subtotal (in the case there are still items left) - using 888 to just check that this field actually got updated
  cart.subtotal = 888
  //Update the carts status
  if (cart.itemsList.size > 0) {
    cart.status = 'partially-completed'
  } else cart.status = 'completed'
  return cart
}

这是我的另一个功能addToCart,可以成功更新地图

//Add item to cart
router.put('/api/cart/:id', (req, res) => {
  if (req.body) {
    CartModel.findById(req.params.id)
      .then(cart => {
        cart = addToCart(cart, req.body)
        cart.save(function(err, doc) {
          if (err) {
            return res.status(400).send(err)
          }
          res.json(doc)
        })
      })
      .catch(err => {
        console.error(err)
        return res.status(400).send(err)
      })
  } else {
    return res.status(404).send('Body is missing.')
  }
})
//Updates the cart with a new item
function addToCart(cart, body) {
  let itemId = body.itemId
  let quantityToAdd = body.quantity || 1
  let price = body.price
  //If the cart already has the item, increment its quantity
  if (cart.itemsList.has(itemId)) {
    let currentQuantity = cart.itemsList.get(itemId)
    cart.itemsList.set(
      itemId,
      currentQuantity + quantityToAdd // Add item to the items_list of the cart and its associated price
    )
  } else {
    // Add the item to the cart
    cart.itemsList.set(itemId, quantityToAdd)
    cart.itemsPrices.set(itemId, price)
  }
  cart.subtotal = cart.subtotal + quantityToAdd * price
  return cart
}

现在,您可以看到两个功能基本上以相同的方式工作。我基本上是对模型返回的购物车对象进行一些更改,然后在对字段进行逻辑处理后,我尝试调用save,并且除2个映射外的每个字段都在checkout调用中更新,但对于addToCart调用。这是结帐调用逻辑(控制台日志)之前和之后的对象。

从数据库收到的购物车的Console.log(购物车)

{ subtotal: 2750,
  status: 'open',
  _id: 5c3bd0e03858b8f48d2cd3af,
  itemsList:
   Map {
     '5c3bc2e2141303f3207cb646' => 1,
     '5c3bc306141303f3207cb647' => 1 },
  itemsPrices:
   Map {
     '5c3bc2e2141303f3207cb646' => 1000,
     '5c3bc306141303f3207cb647' => 1750 },
  __v: 0 }

购物车的Console.log(checkedOutCart)带有要保存的更新字段

{ subtotal: 0,
  status: 'completed',
  _id: 5c3bd0e03858b8f48d2cd3af,
  itemsList: Map {},
  itemsPrices: Map {},
  __v: 0 }

现在还有趣的是我的保存功能res.json(doc)实际上返回了第二个checkedOutCart内容,但实际上并没有将其保存到数据库中。当我致电此购物车的数据库时,我看到了更新的小计,状态,但地图仍然与其中的项目和价格相同(应该为空)。

我不确定自己在做什么错。

更新: 因此,我注意到如果我将itemsList的值更改为仅0而不是从地图中将其删除,它将进行更新。但是,看来我无法用空地图更新它,为什么?

1 个答案:

答案 0 :(得分:0)

我认为此问题可能是由于Map的架构类型引起的。

  

MongooseMap是内置Map类的子类。在这些文档中,我们将互换使用术语“地图”和MongooseMap。在Mongoose中,地图是使用任意键创建嵌套文档的方法。

     

注意:在Mongoose Maps中,键必须是字符串才能将文档存储在MongoDB中

所以,在模式中

let CartSchema = new mongoose.Schema({
  itemsList: {
    type: Map,
    of: String //should be string
  },
  itemsPrices: {
    type: Map,
    of: String //should be string
  },
  subtotal: {
    type: Number,
    default: 0
  },
  status: {
    type: String,
    enum: ['open', 'partially-completed', 'completed'],
    default: 'open'
  },
  fulfilled: {
    type: Date
  }
});