Search code examples
mongodbmongoosemongodb-querynested-documents

MongoDB query for given nested document


Here i have shown only single document but array has such multiple documents, I want to get all the documents which have Internal storage ( Memory -> Internal ) of 128GB

Data :

[
    {
        "_id": "654686dc65bc1013eae01dad",
        "name": "Samsung Galaxy Tab A9+",
        "detailSpec": [
            {
                "category": "Network",
                "specifications": [
                    {
                        "name": "Technology",
                        "value": "GSM / HSPA / LTE / 5G",
                        "_id": "654686dc65bc1013eae01daf"
                    },
                    {
                        "name": "2G bands",
                        "value": "GSM 850 / 900 / 1800 / 1900 ",
                        "_id": "654686dc65bc1013eae01db0"
                    }
                ],
                "_id": "654686dc65bc1013eae01dae"
            },
            {
                "category": "Memory",
                "specifications": [
                    {
                        "name": "Card slot",
                        "value": "microSDXC (dedicated slot)",
                        "_id": "654686dc65bc1013eae01dc6"
                    },
                    {
                        "name": "Internal",
                        "value": "64GB 4GB RAM, 128GB 8GB RAM",
                        "_id": "654686dc65bc1013eae01dc7"
                    }
                ],
                "_id": "654686dc65bc1013eae01dc5"
            },
        ],
        "quickSpec": [
            {
                "name": "Display size",
                "value": "11.0\"",
                "_id": "654686dc65bc1013eae01de2"
            }
        ],
        "__v": 0
    }
]

I have tried this query but problem is, it is considering value field of all categories but i want to consider only "Memory" category and then check only for value fields which is inside the "Memory" category:

const filteredData = await Models.devices.find({
        $and: [
            {
                $and: [
                    {"detailSpec.category": "Memory"},
                    {"detailSpec.specifications.name": "Internal"},
                    {"detailSpec.specifications.value": new RegExp(informationAboutFilter.storage) }
                ]
            }
        ]
    })
console.log(new RegExp(informationAboutFilter.storage))
Output: /128/

Solution

  • You can use $elemMatch to only match objects from your detailSpec array. You can then use the positional operator $ in your projection object because:

    The positional $ operator limits the contents of an array to return the first element that matches the query condition on the array. Use $ in the projection document of the find() method or the findOne() method when you only need one particular array element in selected documents.

    Change your query to:

    const filteredData = await Models.devices.find({
      detailSpec: {
        $elemMatch: {
          category: "Memory",
          "specifications.name": "Internal",
          "specifications.value": {
            $regex: informationAboutFilter.storage
          }
        }
      }
    },
    {
      "detailSpec.$": 1
    })
    

    See HERE for a working example. You will notice the use of "$regex": "128" because the new RegExp function is not available on mongoplayground but they are equivelant.