user2544102
user2544102

Reputation: 91

How to findOneAndUpdate single field with multi nested array documents

I'm stuck on how to update single value in multi nested array documents value with findOneAndUpdate.

My condition goes like this:

Update warehouse amount where the productCode is "abc123", size "41" in warehouse "Hamburg".

I just get back null or bot sizes 41 and 42.

Here is the part of the doc:

{
 "_id": ObjectId("xxxx636309f84479ec0c7b"),
 "productCode": "abc123",
 "brand": "Nike",
 "name": "aaa",
 "model": "Runner",
 "color": "Brown",
 "image": "shoe.jpg",
 "sizes": [{
   "_id": ObjectId("xxxxc636309f84479ec0c7e"),
   "size": "41",
   "wares": [{
     "_id": ObjectId("xxxx2c636309f84479ec0c80"),
     "ware": "Hamburg",
     "amount": 7
    },
    {
     "_id": ObjectId("5db72c636309f84479ec0c7f"),
     "ware": "Berlin",
     "amount": 7
    }
   ]
  },
  {
   "_id": ObjectId("5db72c636309f84479ec0c7c"),
   "size": "42",
   "wares": [{
    "_id": ObjectId("5db72c636309f84479ec0c7d"),
    "ware": "Hamburg",
    "amount": 16
   }]
  }
 ],
 "__v": 0
}

This is what I've tried:

Product.findOneAndUpdate({
  "productCode": "abc123",
  "sizes.size": 41,
  "sizes.wares.ware": "Hamburg"
 }, {
  "$set": {
   "sizes.0.wares.amount": 99
  }
 }, {
  useFindAndModify: false
 },
 (err, products) => {
  if (err) {
   return res.status(422).send(err)
  }
  return res.json(products)
 }
);

How can I solve this?

Upvotes: 1

Views: 65

Answers (2)

rozpuszczalny
rozpuszczalny

Reputation: 98

And to fulfill @ambianBeing, this is how it would be done with findOneAndUpdate:

Product.findOneAndUpdate({
    "productCode": "abc123",
    "sizes": {
        $elemMatch: {
            $and: [
                { size: "41" },
                {
                    wares: {
                        $elemMatch: {
                            ware: "Hamburg"
                        }
                    }
                }]
        }
    }
}, {
    $set: {
        "sizes.$[theSize].wares.$[theWare].amount": 99
    }
}, {
    arrayFilters: [{
        "theSize.size": "41"
    }, {
        "theWare.ware": "Hamburg"
    }]
})

Upvotes: 1

ambianBeing
ambianBeing

Reputation: 3529

Can be done using filtered positional operator $[<identifier>] which is nifty in use cases of nested array updation.

Query (Mongo Shell):

db.collection.update(
  { productCode: "abc123" },
  { $set: { "sizes.$[outer].wares.$[inner].amount": 99 } },
  {
    arrayFilters: [{ "outer.size": "41" }, { "inner.ware": "Hamburg" }],
    multi: false
  }
);

Query with Mongoose Model:

Product.update(
  { productCode: "abc123" },
  { "sizes.$[outer].wares.$[inner].amount": 99 },
  {
    arrayFilters: [{ "outer.size": "41" }, { "inner.ware": "Hamburg" }],
    multi: false
  },
  (err, rawDoc) => {
    if (err) {
      console.error(err);
    }
    console.info(rawDoc);
  }
);

Upvotes: 0

Related Questions