Home > Software engineering >  Mongodb - aggregate match subarray
Mongodb - aggregate match subarray

Time:04-21

I trying to match the data in Subarray for some reason it is grouped like this.

Data :

{
"_id": 1,
"addresDetails": [
    [
        {
            "Name":"John",
            "Place":"Berlin",
            "Pincode":"10001"
        },
        {
            "Name":"Sarah",
            "Place":"Newyork",
            "Pincode":"10002"
        }
    ],
    [
        {
            "Name":"Mark",
            "Place":"Tokyo",
            "Pincode":"10003"
        },
        {
            "Name":"Michael",
            "Place":"Newyork",
            "Pincode":"10002"
        }
    ]
]
}

I tried with this Match query:

{
  "$match":{
    "attributes":{
       "$elemMatch":{
            "$in":["Mark"]
            }
        }
    }
}

I am getting No data found , How do i match the elements in this subarrays.

CodePudding user response:

Query

  • aggregation way, in general if you are stuck and query operators or update operators seems not enough, aggregation provides so much more operators, and its alternative.
  • 2 nested filter in the 2 level arrays to find a Name in array [Mark]

*maybe there is a shorter more declarative way with $elemMatch, and possible a way to use index, also think about schema change, maybe you dont really need array with array members (the bellow doesnt use index)

*i used addressDetails remove the one s else you will get empty results

Playmongo

aggregate(
[{"$match": 
   {"$expr": 
     {"$ne": 
       [{"$filter": 
           {"input": "$addressDetails",
            "as": "a",
            "cond": 
             {"$ne": 
               [{"$filter": 
                   {"input": "$$a",
                    "as": "d",
                    "cond": {"$in": ["$$d.Name", ["Mark"]]}}},
                []]}}},
        []]}}}])

CodePudding user response:

You can apparently nest elemMatch as well, e.g.:

db.collection.find({
  "addresDetails": {
    $elemMatch: {
      $elemMatch: {
        "Name": "Mark"
      }
    }
  }
})

This matches your document, as shown by this mongo playground link, but is probably not very efficient.

Alternatively you can use aggregations. For example unwind may help to flatten out your nested arrays, and allow for easier match afterwards.

db.collection.aggregate([
  {
    "$unwind": "$addresDetails"
  },
  {
    "$match": {
      "addresDetails.Name": "Mark"
    }
  }
])

You can find the mongo playground link for this here. But unwind is usually not preferred as the first stage of the aggregation pipeline either, again because of performance reasons.

Also please note that the results for these 2 options are different!

  • Related