【问题标题】:mongoose updateOne with upsert is not working带有 upsert 的猫鼬 updateOne 不起作用
【发布时间】:2020-09-04 04:29:43
【问题描述】:
let cart = req.body.params.cart // array of objects that needs to be updated if exists in db, if not upsert it. 

let userid = req.body.params.uid

for (let i = 0; i < cart.length; i++) {
    Cart.updateOne({ user: userid, 'cart.product': cart[i].product._id },
        {
            $set: {
                'cart.$.quantity': cart[i].quantity
            }
        },
        { upsert: true }// works without this line of code, updates the objects if exists
    )
}

我的购物车型号:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const CartSchema = new Schema({
    user: {
        type: Schema.Types.ObjectId,
        ref: 'users'
    },
    cart: [{
        product: {
            type: Schema.Types.ObjectId,
            ref: 'productlist'
        },
        quantity: {
            type: Number
        },
        date: {
            type: Date,
            default: Date.now
        }
    }]

})

module.exports = Cart = mongoose.model('cart', CartSchema)

我正在尝试使用购物车数组中的新商品更新用户购物车。我需要检查产品是否存在,如果是更新数量,如果不将其推入用户的购物车。不知何故,它不适用于 $upsert。如果对象 id 存在于用户的购物车中,则没有 $upsert 的文档会得到更新。

具有大量混乱的工作版本。我觉得有一种更好的方法可以做到这一点,就像我在上面尝试做的那样。我会感谢任何帮助,减少这里的混乱。

Cart.find({ user: req.body.params.uid })
        .then(userCart => {
            if (userCart[0].cart.length === 0) {
                for (let i = 0; i < cart.length; i++) {
                    Cart.updateOne({ user: req.body.params.uid }, {
                        $push: {
                            cart: {
                                product: cart[i].product._id,
                                quantity: cart[i].quantity
                            }
                        }
                    }).catch(err => console.log(err))
                }
            }
            else {

                cart.reduce((acc, element) => {
                    let index = userCart[0].cart.findIndex(val => val.product._id == element.product._id)
                    if (index !== -1) {

                        Cart.findOneAndUpdate({ user: req.body.params.uid, 'cart.product': element.product._id },
                            {
                                $set: {
                                    'cart.$.quantity': element.quantity
                                }
                            },
                            { new: true }
                        ).then(a => console.log(a))
                    }
                    else {
                        Cart.updateOne({ user: req.body.params.uid }, {
                            $push: {
                                cart: {
                                    product: element.product._id,
                                    quantity: element.quantity
                                }
                            }
                        }).catch(err => console.log(err))
                    }
                    acc.push(element)
                    return acc
                }, [])
            }
        })

来自数组购物车的样本值

   product: {
     _id: '5eaf8eeac436dbc9b7d75f35',
     name: 'Strawberry',
     category: 'organic',
     image: '/productImages/australian.jpg',
     price: '9.65'
   },
   quantity: 6

数据库中的样品车:

   _id: 5ec12ea36ccf646ff5aeef0c,
   user: 5ec11a8f69ccf46e0e19c5ef,
   cart: [
     {
       date: 2020-05-18T10:26:38.751Z,
       _id: 5ec262de5829f081b1ea96d7,
       product: 5eaf8eeac436dbc9b7d75f35,
       quantity: 8
     },
     {
       date: 2020-05-18T12:11:57.168Z,
       _id: 5ec27b8dd2949886308bebd6,
       product: 5eaf8f61c436dbc9b7d75f36,
       quantity: 6
     }
   ]

【问题讨论】:

  • 这能回答你的问题吗? MongoDB: upsert sub-document
  • 不是真的,谢谢你的参考。 @PuneetSingh
  • @PuneetSingh 发布并更新仅供参考..
  • 您能否也发布您在 cart.reduce 中使用的数组购物车的示例值
  • 收到的购物车是满的购物车吗?或者如果我有一个与其他产品一起保存的“旧”购物车,我们应该维护它们?

标签: javascript node.js mongodb mongoose


【解决方案1】:

我认为最好的解决方案是先在 node.js 代码中匹配旧购物车和新购物车,然后更新它,因为下面是步骤和代码。

  1. 从新购物车中创建一个仅包含 productid 及其数量的数组
  2. 然后从数据库中获取旧的购物车详细信息
  3. 匹配两个购物车并创建两个不同的数组,一个仅包含购物车中的新产品,另一个包含旧购物车中已有的 productid

现在您有两个单独的数组,它们只需在 2 个查询中即可轻松更新,而不是您在代码中使用的循环或多个查询。我也试着用代码cmets来解释一下。

// First get all the new cart productid and quantity in an array
var cartArray = cart.map(obj => {
    return {product: obj.product._id, quantity: obj.quantity}
})

Cart.findOne({ user: req.body.params.uid })
   .then(userCart => {

var productIds = userCart.cart.map(obj => obj.product)

// array of products id and quantity which are already there in old cart
var productsOld = cartArray.filter(obj => {
  return productIds.includes(obj.product)
})

// array of products id and quantity which are not there in old cart
var productsNew = cartArray.filter(obj => {
  return !productIds.includes(obj.product)
})

//First, we will add the all new products which are in the new cart
Cart.findOneAndUpdate({ user: req.body.params.uid }, {
  $push: {
    cart: {
      $each: productsNew
    }
  }
}, {
  new: true
}).then(function(updatedUserCart){
  // Here we are getting now the updated cart with new products added
  // Now we need to update quantity of old products

  // Instead of running query in loop, we will update the quantity in array map
  // and replace the whole cart in the document
  var newCart = updatedUserCart.cart.map(obj => {
    var matchProduct = productsOld.filter(oldObj => {
      return oldObj.product == obj.product
    })
    if (matchProduct.length > 0) {
      obj.quantity = parseInt(obj.quantity) + parseInt(matchProduct[0].quantity)
      return obj
    } else {
      return obj
    }
  })

  Cart.updateOne({ user: req.body.params.uid }, {
      $set: {
          cart: newCart
      }
  })
}).catch(err => console.log(err))
})

免责声明:我没有尝试在我的系统上运行代码,因此可能存在拼写错误或语法错误,但希望您了解流程和逻辑

【讨论】:

  • 是的,有道理。谢谢你。一个问题是,当您在最后一次查询中更新数据库购物车时,updateOne 不起作用,但是当我使用 findOneAndUpdate 时,它​​起作用了。但我不需要它来返回任何东西。您知道 updateOne 不起作用的原因吗?
  • 应该可以,如果不行你也可以试试,Cart.update
猜你喜欢
  • 2020-02-18
  • 2015-11-18
  • 2020-09-06
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 2013-06-19
  • 2023-03-03
相关资源
最近更新 更多