Search code examples
javamongodbspring-bootreactive

Finding exact match in MongoDB query where search criteria is applied to the object level in the list


I have a requirement of fetching data from mongodb and being done using Java Spring Reactive Mongodb library. I am using the following code for this:

Criteria criteria = Criteria.where(QUERYFIELD1).in(listOfIds)
                    .andOperator(Criteria.where(QUERYFIELD2).gte(ChildDate));
Query query = Query.query(criteria).noCursorTimeout();
reactiveMongoTemplate.find(query, Document.class, COLLECTIONNAME);

Where QUERYFIELD1 is "ChildId" and QUERYFIELD2 is a "ChildDate". Following is the structure of my document:

{
"_id": {
    "$oid": "6296968fa63757a93e1cd123"
},
"Level1": {
    "Level2": [
        {
            "ChildId": "1234",
            "ChildDate": {
                "$date": "2021-04-01T04:00:00.000Z"
            }
        },
        {
            "ChildId": "5678",
            "ChildDate": {
                "$date": "2017-05-16T04:00:00.000Z"
            }
        },
        {
            "ChildId": "3456",
            "ChildDate": {
                "$date": "2008-09-16T04:00:00.000Z"
            }
        },
        {
            "ChildDate": {
                "$date": "2022-06-01T04:00:00.000Z"
            },
            "ChildId": "7891"
        }
    ] 
}

}

I am trying to find a document which should match the criteria within the Objects under Level2. For e.g. if My criteria has ChildId as "3456" and ChildDate as "2022-06-01T04:00:00.000Z" then I should get empty results as ChildId is matching with Object3 and ChildDate is matching with Object4. But when I use below query, I get 1 record as the match:

{ "Level1.Level2.ChildId" : "3456", "Level1.Level2.ChildDate" : { $gt: new Date("2022-01-01T05:00:00.000+00:00")}}

I am trying to achieve this using Spring Reactive MongoDB. Please help.


Solution

  • You can use $elemMatch for finding the documents that their array includes an item which matches the conditions:

    db.collection.find({
      "Level1.Level2": {
        $elemMatch: {
          ChildId: "3456",
          ChildDate: {$gt: new Date("2008-09-16T05:00:00.000Z")}
        }
      }
    })
    

    See how it works on the playground example