Search code examples
node.jstypescriptmongodbmernmongoose-schema

Getting this Error : "E11000 duplicate key error collection"


I am making an ecommerce website using MERN stack + typescript. Here I trying to implement a functionality where user can give review to the product. A particular user can give only one review to one product.

User Schema

import mongoose from "mongoose";
import validator from "validator";

const userSchema = new mongoose.Schema({
    googleId: {
        type: String
    },
    name: {
        type: String,
        required: [true, "Please enter your name"]
    },
    number: {
        type: Number,
        required: [true, "Please enter your mobile number"]
    },
    dob: {
        type: Date,
        required: [true, "Please enter your dob"]
    },
    email: {
        type: String,
        required: [true, "Please enter your email"],
        validate: validator.isEmail,
    },
    password: {
        type: String,
        required: [true, "Please enter your password"]
    },
    photo: {
        type: String
    }, 
    gender: {
        type: String,
        enum: ["Male", "Female", "LGBTQ+"],
        required: [true, "Please enter your gender"]
    },
    role: {
        type: String,
        enum: ["User", "Admin"],
        default: "User"
    }
}, {
    timestamps: true
});

export const UserModel = mongoose.model("User", userSchema);

Product Schema

import mongoose from "mongoose";

const productSchema = new mongoose.Schema({
    name: {
        type: String,
        required: [true, "Please enter the name of the product"]
    },
    stock: {
        type: Number,
        required: [true, "Please enter the stock of the product"]
    },
    price: {
        type: Number,
        required: [true, "Please enter the quantity of the product"]
    },
    photo: {
        type: String,
        required: [true, "Please enter the photo of the product"]
    },
    description: {
        type: String,
        required: [true, "Please enter the description of the product"]
    },
    category: {
        type: String,
        required: [true, "Please enter the name of the product"]
    },
    brand: {
        type: String,
        required: [true, "Please enter the brand of the product"]
    }
}, {
    timestamps: true,
});

const productModel = mongoose.model("Product", productSchema);

export default productModel;

Comment Schema

import mongoose, { Document, Schema, Model } from "mongoose";

const commentSchema = new Schema({
    user: {
        type: Schema.Types.ObjectId,
        ref: "User",
        required: true,
    },
    product: {
        type: Schema.Types.ObjectId,
        ref: "Product",
        required: true
    },
    title: {
        type: String,
        required: [true, "Please Enter the title of your comment"]
    },
    description: {
        type: String,
        required: [true, "Please Enter the description of your comment"]
    }
});

export const commentModel = mongoose.model<Comment>('Comment', commentSchema);

Now for the first time, when a user is posting a comment, it is saved in the database, but when the same user is trying to give another review to a different product, I am getting an error: Error : "E11000 duplicate key error collection: ECommerce.comments index: user_1 dup key: { user: ObjectId('65f2032cf4f5ba356d94604c') }"

Now below is the function for adding a new comment:

export const newComment = async(req:Request<{}, QueryType,CommentBodyType>, res:Response, next:NextFunction) => {
    try {
        const user = req.user?._id;
        const {title, description} = req.body;

        if (!title || !description) {
            return next(new MyErrorClass("Please fill all the necessary information", 404));
        }

        const {productId} = req.query;

        if (!productId) {
            return next(new MyErrorClass("No Product Selected", 400));
        }

        const productFound = await productModel.findById(productId);
        if (!productFound) {
            return next(new MyErrorClass("No product found", 404));
        }

        // todo -> Handel the case when the same user is going to add multiple comments for a single product. Still it gives error.
        const commentExists = await commentModel.findOne({
            user,
            product:productId
        });
        
        if (commentExists) {
            return next(new MyErrorClass("You have already added a comment for this product", 400));
        }

        await commentModel.create({
            user,
            product: productId,
            title,
            description
        });

        return res.status(201).json({
            success: true,
            message: `Comment added successfully !`
        });
    } catch (error:any) {
        return next(new MyErrorClass(error.message || "Internal Server Error", 500));
    }
}

All I want to do is I want in my comment schema, both user and product should act as a key, because then only it can solve my problem.


Solution

  • E11000 duplicate key error indicates that MongoDB is preventing you from inserting a duplicate value into a field that has a unique index.

    you can check if you have any unique index properties by db.<my_collection>.getIndexes(). If some of those indexes are unique, you will see a key named "unique" with the value true.

    If you want to allow users to post multiple comments, you should remove the unique index from the user field. if you want to prevent a user from commenting on the same product more than once, you could create a compound unique index on both user and product

    commentSchema.index({ user: 1, product: 1 }, { unique: true });