如何在mongodb中避免重复密钥错误收集

raogr8fs  于 2021-09-13  发布在  Java
关注(0)|答案(2)|浏览(260)

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

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 dup密钥:{items.productid:null},堆栈:mongoerror:e11000重复密钥错误集合:elec-store.carts索引:items.productid_1 dup密钥”
这是add函数

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
}
voj3qocg

voj3qocg1#

我使用mongoose.schema创建新的模式,然后在引用其他模式时,我会这样做:

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

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

zmeyuzjn

zmeyuzjn2#

您可以使用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更新

相关问题