如何避免mongodb中的重复键错误收集

Posted

技术标签:

【中文标题】如何避免mongodb中的重复键错误收集【英文标题】:how to avoid duplicate key error collection in mongodb 【发布时间】:2021-09-20 20:35:23 【问题描述】:

我想为我的网站构建一个购物车,这是购物车的架构:

const productSchema = require("./product")[1];

const cartItemSchema = new Schema<CartItem>(
  
    product: productSchema, 
    quantity: 
      type: Number,
      required: true,
      min: [1, "Quantity can not be less then 1."],
    ,
  ,
  
    timestamps: true,
  
);

const CartSchema = new Schema(
  
    userID: 
      type: Schema.Types.ObjectId,
      ref: "User",
    ,
    items: [cartItemSchema],
  ,
   timestamps: true 
);

module.exports = model<Cart>("Cart", CartSchema);

问题是,当我在特定用户购物车中添加产品时,当同一产品已添加到另一个用户购物车文档时,我收到此错误:

“消息”:“无法添加到购物车 E11000 重复键错误集合:elec-store.carts 索引:items.productID_1 重复键: items.productID:null ,堆栈:MongoError:E11000 重复键错误集合:elec -store.carts 索引:items.productID_1 复制键

这是添加功能

 public async add(cartItem: CartItem, userID: string): Promise<Cart> 
    let cartInDB = null;

    await CartModel.findOne( userID: userID , (err, cart) => 
      cartInDB = cart;
    );

    if (AppUtils.hasValue(cartInDB)) 
      const index = cartInDB.items.findIndex(
        (item) => item.product._id.toString() === cartItem.product._id
      );

      if (index !== -1) 
        cartInDB.items[index].quantity =
          cartInDB.items[index].quantity + cartItem.quantity;
        cartInDB.items[index].product._id = cartItem.product._id;

        const cartAfterAdding = await cartInDB.save();

        return cartAfterAdding;
       else 
        await CartModel.update(
           _id: cartInDB._id ,
           $push:  items: cartItem  
        );
      

      return cartInDB;
     else 
      const itemsArray: CartItem[] = [];
      itemsArray.push(cartItem);

      let createdCart = new CartModel(
        userID: userID,
        items: itemsArray,
      );

      await createdCart.save(); \\ this is where the problem occurs


      return createdCart;
    
  

这就是我的购物车在 mongodb 文档中的样子:

 db.carts.find().pretty()

        "_id" : ObjectId("60ea9fb81b2b4c048c3b1544"),
        "userID" : ObjectId("60dee5e1da81bd274cd304de"),
        "items" : [
                
                        "_id" : ObjectId("60ea9fb81b2b4c048c3b1545"),
                        "product" : 
                                "_id" : ObjectId("60e62cb21f74572b7c0b3a30"),
                                "name" : "tv",
                                "description" : "the best tv",
                                "categoryID" : 2,
                                "quantity" : "2",
                                "serialNumber" : "226swaq12",
                                "price" : 2000,
                                "imgUrl" : "https://www.seekpng.com/png/full/774-7744281_samsung-electronics-samsung-electronic-product-png.png"
                        ,
                        "quantity" : 6,
                        "createdAt" : ISODate("2021-07-11T07:37:29.790Z"),
                        "updatedAt" : ISODate("2021-07-11T07:38:15.583Z")
                ,
                
                        "_id" : ObjectId("60eaa16b1b2b4c048c3b155d"),
                        "product" : 
                                "_id" : ObjectId("60e066009be1060748201ad3"),
                                "name" : "samsung tv",
                                "description" : "the best tv",
                                "quantity" : "2",
                                "categoryID" : 2,
                                "serialNumber" : "2212",
                                "price" : 2000,
                                "imgUrl" : "https://www.seekpng.com/png/full/774-7744281_samsung-electronics-samsung-electronic-product-png.png"
                        ,
                        "quantity" : 9,
                        "updatedAt" : ISODate("2021-07-11T07:46:19.313Z"),
                        "createdAt" : ISODate("2021-07-11T07:44:43.764Z")
                
        ],
        "createdAt" : ISODate("2021-07-11T07:37:29.792Z"),
        "updatedAt" : ISODate("2021-07-11T07:46:19.314Z"),
        "__v" : 0

【问题讨论】:

【参考方案1】:

我使用 mongoose.Schema 创建新的模式,然后在引用不同的模式时,我会这样做:

product:  type: mongoose.Schema.Types.ObjectId, ref: 'product' ,

如果稍后您还需要显示产品信息 (db.carts.find()),您可以使用 populate() 替换所有产品条目的引用。

【讨论】:

【参考方案2】:

你可以使用 upsert true。

  db.collection.update(
 <query>,
 <update>,
 
  upsert: <boolean>,
  multi: <boolean>,
  writeConcern: <document>,
  collation: <document>,
  arrayFilters: [ <filterdocument1>, ... ],
  hint:  <document|string>        // Available starting in MongoDB 4.2

)

例如-

      db.books.update(
       item: "ZZZ135" ,   // Query parameter
                           // Replacement document
         item: "ZZZ135",
         stock: 5,
         tags: [ "database" ]
      ,
       upsert: true       // Options
     )

这可能会有所帮助:Mongo Update

【讨论】:

以上是关于如何避免mongodb中的重复键错误收集的主要内容,如果未能解决你的问题,请参考以下文章

使用空数组添加新用户记录时出现“E11000 重复键错误收集”

E11000 重复键错误收集 info.subs: null

E11000 重复键错误收集:ad-network.users 索引:username_1 重复键: : null

在 mongo 中插入 doc 时 E11000 重复键错误收集

E11000 重复键错误收集:db.products 索引:product_id_1 重复键: product_id:null

1000多个项目中的十大JavaScript错误以及如何避免