Ekansh Rastogi
Ekansh Rastogi

Reputation: 2526

MongoDb : Find and filter values from nested map

I have some date in mongo db

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "orgId": "606abce197dc265ac41ae82c",
    "registrations": {
      "id1": {
        "status": "status",
        "topStage": {
          "id": "stage1",
          "name": "stage1"
        }
      },
      "id2": {
        "status": "status",
        "topStage": {
          "id": "stage1",
          "name": "stage1"
        }
      },
      "id3": {
        "status": "status",
        "topStage": {
          "id": "stage2",
          "name": "stage2"
        }
      }
    }
  }
]

I am expecting to pass a stage id (at path registrations-> topStage -> id) and return all matching key values.

i have written following query

db.collection.aggregate([
  {
    $project: {
      teams: {
        $objectToArray: "$registrations"
      },
      original: "$$ROOT"
    }
  },
  {
    "$project": {
      "teams": {
        "$filter": {
          "input": "$teams",
          "as": "team",
          "cond": {
            "$eq": [
              "$$team.v.topStage.id",
              "stage1"
            ]
          }
        }
      }
    }
  },
  {
    "$project": {
      "registrations": {
        "$arrayToObject": "$teams"
      }
    }
  }
])

It does return me right values for stage1 as stage id

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "registrations": {
      "id1": {
        "status": "status",
        "topStage": {
          "id": "stage1",
          "name": "stage1"
        }
      },
      "id2": {
        "status": "status",
        "topStage": {
          "id": "stage1",
          "name": "stage1"
        }
      }
    }
  }
]

and for stage2 as stage id, it returns

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "registrations": {
      "id3": {
        "status": "status",
        "topStage": {
          "id": "stage2",
          "name": "stage2"
        }
      }
    }
  }
]

Can someone let me know if this is the best way to write this query or this can be simplified ??

Upvotes: 1

Views: 923

Answers (1)

Gibbs
Gibbs

Reputation: 22964

It's the correct way to do it but there will be performance impact in the following cases.

  • If you don't have any other match condition against the indices
  • if you have a match condition and it matches few docs where registrations has more objects

Other best option you could do is that altering the schema.

  • you can keep registrations.id1 as registrations : { id:1, status_id: 2}
  • or you could alter the way such that it will not need to use objectToArray on larger set
  • if your data is huge, I would recommend to add an index on nested status Id field.

And mongo documentation itself suggests to evaluate multiple schemas for any data to get the best out of it.

Upvotes: 1

Related Questions