Incremental ID using countDocuments becomes duplicate

I use Mongoose ODM. I have a field stringID in Invoice model which is incremental. What I do is, count the documents and add 1 for the next invoice id.

let allCount = await Invoice.countDocuments().exec();
allCount = allCount + 1;
const stringID = 'I' + allCount.toString().padStart(6, "0");

const invoice = new Invoice({
    stringID,
    customerName: req.body.customerName,
});

invoice
    .save()
    .then(async data => {})
    .catch(err => {})

But the problem is I get duplicated stringID sometimes. I think concurrent insert operation is the cause but I want to know what is the exact cause and what is the possible solution to this?

Hey @Zahid_Hasan1,

Welcome to the MongoDB Community forums :sparkles:

I think this issue is likely due to concurrent insert operations. When multiple requests or processes try to create new Invoice documents simultaneously, they may retrieve the same document count before incrementing it, leading to duplicate stringID values.

To overcome this issue, you can define a unique index on the stringID field in your Mongoose schema:

const invoiceSchema = new mongoose.Schema({
    stringID: {
        type: String,
        unique: true, // This ensures uniqueness
    },
});
...
const Invoice = mongoose.model('Invoice', invoiceSchema);

Secondly, you can modify your code to handle potential duplicate key errors that may occur when inserting a document with a duplicate stringID. You can use a try-catch block to catch and handle these errors:

const stringID = 'I' + allCount.toString().padStart(6, '0');

const invoice = new Invoice({
    stringID,
    customerName: req.body.customerName,
});

try {
    const savedInvoice = await invoice.save();
    // success
} catch (error) {
    if (error.code === 11000) {
        // Duplicate key error --> handle it appropriately or retry with a new ID
    } else {
        // Handle other errors
    }
}

By defining a unique index on the stringID field and handling duplicate key errors, you can ensure that no two invoices will have the same stringID, even in concurrent insertion scenarios. If a duplicate key error occurs, you can generate a new stringID and attempt to save the document again.

However, this is just a general approach and I would recommend you test this behavior with your specific use case, to ensure that the application can handle different scenarios.

Best regards,
Kushagra

2 Likes

Thank you Kushagra for the reply… I will test this approach and let you know if it works perfectly.

1 Like