newdeveloper
newdeveloper

Reputation: 1451

Insert a new object under embedded subdocument

This is my sample record:

enter image description here

Building id as highlighted in above image, has a subdocument gateways. I am able to find building id but not sure how to push / insert a new object gateway under gateways subdocument.

here is my body for new gateway object to be inserted from request.

{
    "gatewayName": "gatewayName",
    "gatewayKey": "sampleKey",
    "suite": "3300"
}

This is what I am trying currently. It returns the same document.
First I find account, then get building. then Find building based on buildingId provided. There I need to insert a new gateway object under Gateways subdocument

   const account = await Account.findOne({ _id: new ObjectId(req.query.id) });
      const allBuildings = account.buildings;
      const filteredBuildings = _.filter(allBuildings, { _id: ObjectId(req.query.buildingId) });
      const gateways = _.flatMap(filteredBuildings, b => b.gateways);

      gateways.push({
        "gatewayName": "TD Bank Tower22223",
        "gatewayKey": "sdasdasdasd",
                  "suite": "3300"
      }
      );
      const updatedAccount = await account.save();
      console.log(updatedAccount)
res.json(updatedAccount);

Upvotes: 0

Views: 77

Answers (2)

newdeveloper
newdeveloper

Reputation: 1451

I was able to dig through sub documents using even easier method. I am posting answer here so others can use it.

if you want to find embedded sub documents:

var gateway = account.buildings.id(req.params.buildingId).gateways.id(req.params.gatewayId);

using .id(_id) helps to find object by id quicker.

if you want to remove an object from deeply nested subdocument:

account.buildings.id(req.params.buildingId).gateways.id(req.params.gatewayId).devices.pull(req.params.deviceId);

above will remove the element. then you just have to save the document using collectionName.save()

Upvotes: 0

Samuel Goldenbaum
Samuel Goldenbaum

Reputation: 18909

Yes, you can do the find and update in a single findOneAndUpdate using $elemMatch, $addToSet and the $ operators.

First match on the document id and the building id within the array. You can then access the matched building using the $ operator and use $addToSet to insert a new array element.

Example:

const gateway = {
    "gatewayName": "gatewayName",
    "gatewayKey": "sampleKey",
    "suite": "3300"
};

const update = await Account.findOneAndUpdate(
    {
        _id: new ObjectId(req.query.id),
        buildings: {$elemMatch: {_id: {$eq: ObjectId(req.query.buildingId)}}}
    },
    {
        $addToSet: {"buildings.$.gateways": gateway}
    },
    {
        new: true
    }
);

Upvotes: 1

Related Questions