0

My mongodb database includes a collection of users and each user has an array of shops and each shop has an array of products. Here is a simplified version of my collection structure:

[
    {
        "_id": "60e66b70da2439232e330415",
        "name": "User1 Name",
        "shops": [
            {
                "_id": "60e7c9e2be0d8f03544a03b8",
                "shopName": "User1 Shop1 Name",
                "products": [
                    {
                        "_id": "60e9e9e8105d6021a2e91535",
                        "title": "User1 Shop1 Product1 Title"
                    },
                    {
                        "_id": "60e9f4a0105d6021a2e91536",
                        "title": "User1 Shop1 Product2 Title"
                    }
                ]
            },
            {
                "_id": "60e8e8c00f3986577cb968c9",
                "shopName": "User1 Shop2 Name",
                "products": [
                    {
                        "_id": "60e9f4fe105d6021a2e91537",
                        "title": "User1 Shop2 Product1 Title"
                    },
                    {
                        "_id": "60e9f515105d6021a2e91538",
                        "title": "User1 Shop2 Product2 Title"
                    }
                ]
            }
        ]
    },
    {
        "_id": "60e66b93da2439232e330416",
        "name": "User2 Name",
        "shops": [
            {
                "_id": "60e69698e76cad44e49e1fc8",
                "shopName": "User2 Shop1 Name",
                "products": [
                    {
                        "_id": "60e9f588105d6021a2e91539",
                        "title": "User2 Shop1 Product1 Title"
                    },
                    {
                        "_id": "60e9f59c105d6021a2e9153a",
                        "title": "User2 Shop1 Product2 Title"
                    }
                ]
            },
            {
                "_id": "60e902b441e9df63c7fbcb49",
                "shopName": "User2 Shop2 Name",
                "products": [
                    {
                        "_id": "60e9f5c9105d6021a2e9153b",
                        "title": "User2 Shop2 Product1 Title"
                    },
                    {
                        "_id": "60e9f5de105d6021a2e9153c",
                        "title": "User2 Shop2 Product2 Title"
                    }
                ]
            }
        ]
    }
]

I have an api endpoint like .../api/products/60e9f5de105d6021a2e9153c. This endpoint includes a parameter which is a productId. I have the following two codes to update the product data from my mongodb collection, but my ode won't work and won't update the intended element.

My endpoint code:

app.put("/api/products/:productID", (req, res) => {
    let productID = req.params.productID;
    let productData = req.body;
    
    myData.updateProductByProductId(productData, productID)
    .then(confMsg => res.json({"message": confMsg}))
    .catch(err => res.json({"message": err}));

});

My DataService code:

updateProductByProductId: function(productData, productID){
            return new Promise((resolve, reject)=>{
                User.updateOne(
                    { "shops.products._id" : productID},
                    { $set: { "shops.products.$":  productData } }
                ).exec().then(()=>{
                    resolve(`product ${productID} successfully updated.`)
                }).catch(err=>{
                    reject(err);
                });
            });
        }

The above code returns this error:

{
    "message": {
        "driver": true,
        "name": "MongoError",
        "index": 0,
        "code": 28
    }
}

I also tried using { "shops.products._id" : mongoose.Types.ObjectId(productID)} instead of { "shops.products._id" : productID} and got the same result.

Thank you very much in advance for your time and kind advice.

2 Answers 2

1

I am adding the mongodb query for your question. You can use mongoose for the same.

await db1.updateOne(
        {
            "shops": {
                "$elemMatch": {
                    "products._id": productID
                }
            }
        },
        {
            "$set": {
                "shops.$.products.$[inner].name": "new name",
                "shops.$.products.$[inner].description": 'description',
                "shops.$.products.$[inner].oName": 'oName',
                "shops.$.products.$[inner].type": 'type'
            }
        },
        {
            "arrayFilters": [
                { "inner._id": productID }
            ]
        }, (err, result) => {
            if (err) {
                console.log('Error updating service: ' + err);
                res.send({ 'error': 'An error has occurred' });
            } else {
                // console.log('' + result + ' document(s) updated');
                res.send(result);
            }
        })

otherwise to update the whole product details you can use the following

let newDetails = {
        _id: productID,
        name: "newName11", Description: "Description11"
    }

await db1.updateOne(
        {
            "shops": {
                "$elemMatch": {
                    "products._id": productID
                }
            }
        },
        {
            "$set": {
                "shops.$.products.$[inner]": newDetails
            }
        },
        {
            "arrayFilters": [
                { "inner._id": productID }
            ]
        }, (err, result) => {
            if (err) {
                console.log('Error updating service: ' + err);
                res.send({ 'error': 'An error has occurred' });
            } else {
                // console.log('' + result + ' document(s) updated');
                res.send(result);
            }
        })
Sign up to request clarification or add additional context in comments.

Comments

0

You can use arrayFilter to filter the array element

User.update(
 { "shops.products._id": mongoose.Types.ObjectId("60e9f5de105d6021a2e9153c") },
 { $set: { "shops.$.products.$[elem].title": "new title" } },
 { arrayFilters:[{"elem._id":mongoose.Types.ObjectId("60e9f5de105d6021a2e9153c")}]}
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.