Cannot add object with composite key to IndexedDB objectStore. Key already exists in the object store. When only one entry is the same

Issue

I have an objectStore with the following key:
Composite key

When I add an object with the same productId, but different shopName transaction reports the error: ConstraintError: Key already exists in the object store..
That’s how I created objectStore:

openRequest.onupgradeneeded = e => {
    // @ts-ignore
    db = e.target.result;
    const objectStore = db.createObjectStore('cart', {keyPath: ['productId', 'shopName']})
    console.log('Db set up')
}

That’s how I add objects:

    function addProduct(product: CartProduct) {
        const pk = {productId: product.productId, shopName: product.shopName}

        const {transaction, objectStore, cursorRequest} = getIndexedDbTriplet();

        cursorRequest.onsuccess = e => {
            // @ts-ignore
            const cursor = e.target.result
            if (cursor) {
                if (cursor.primaryKey[0] === pk.productId && cursor.primaryKey[1] === pk.shopName) {
                    cursor.value.count++
                    cursor.update(cursor.value)
                    // @ts-ignore
                    console.log(`Found ${JSON.stringify(pk)} in db and updated`)
                    return
                }
                cursor.continue()
            }
            objectStore.add(product)
            transaction.oncomplete = () => console.log(`Added ${JSON.stringify(pk)} to db`)
        }

        // @ts-ignore
        transaction.onerror = e => console.log(`Transaction to add product failed: ${JSON.stringify(pk)} ${e.target.error}`)
    }
export class CartProduct {
    readonly productId: number
    readonly name: string
    readonly price: number
    readonly shopName: string
    readonly imageUri: string
    readonly weight: number
    readonly count = 1

    constructor(productId: number, name: string, price: number, shopName: string, imageUri: string, weight: number) {
        this.productId = productId
        this.name = name
        this.price = price
        this.shopName = shopName
        this.imageUri = imageUri
        this.weight = weight
    }
}
export function getIndexedDbTriplet() {
    const transaction = db.transaction('cart', 'readwrite')
    const objectStore = transaction.objectStore('cart')
    const cursorRequest = objectStore.openCursor()
    return {transaction, objectStore, cursorRequest};
}

All the code is in the same file.

Solution

Replacing add with put function calling solved the problem.

Answered By – Aliensis

Answer Checked By – Timothy Miller (AngularFixing Admin)

Leave a Reply

Your email address will not be published.