3

I am having trouble in returning only the matched embedded document using MongoDB ODM query builder in PHP. Each embedded document has a MongoID generated at the time of creation. Following is my document structure of collection Project:

{ 
    "_id" : ObjectId("59f889e46803fa3713454b5d"), 
    "projectName" : "usecase-updated", 
    "classes" : [
        {
            "_id" : ObjectId("59f9d7776803faea30b895dd"), 
            "className" : "OLA"
        }, 
        {
            "_id" : ObjectId("59f9d8ad6803fa4012b895df"), 
            "className" : "HELP"
        }, 
        {
            "_id" : ObjectId("59f9d9086803fa4112b895de"), 
            "className" : "DOC"
        }, 
        {
            "_id" : ObjectId("59f9d9186803fa4212b895de"), 
            "className" : "INVOC"
        }
    ]
}

Now i want to retrieve from the database only the class from the classes embedded documents which meets my criteria (i.e. class with a specific id).This is how i am building the query:

$qb = $dm->createQueryBuilder('Documents\Project');
$projectObj = $qb
    ->field('id')->equals("59f889e46803fa3713454b5d")
    ->field('classes')->elemMatch(
        $qb->expr()->field("id")->equals(new \MongoId("59f9d7776803faea30b895dd"))
    )
    ->hydrate(false)
    ->getQuery()
    ->getSingleResult();

First i match with the project id then i match with the embedded document class id. I was expecting it to return only the embedded document of OLA like this:

{ 
   "_id" : ObjectId("59f889e46803fa3713454b5d"), 
    "projectName" : "usecase-updated", 
    "classes" : [
          {
            "_id" : ObjectId("59f9d7776803faea30b895dd"), 
            "className" : "OLA"
          }
     ]
}

But doctrine is returning the whole Project record (shown in the start of question).I also tried with aggregation query building with the $match aggregation still the results are same the query i created with aggregation builder is as follows:

$qb = $dm->createAggregationBuilder('Documents\Project');
    $projectObj = $qb
        ->match()
        ->field('id')->equals($projectId)
        ->field('classes._id')->equals(new \MongoId($classId))
        ->execute()
        ->getSingleResult();

Can someone help me with regards to this issue? How can i build query that i get the desired result as mentioned above.

3
  • 1
    ODM works with whole documents. Either filter it in the app, or use aggregation. Commented Nov 1, 2017 at 16:56
  • @AlexBlex i tried with that as well but still the results were same. I updated the question with the aggregation query builder Commented Nov 1, 2017 at 17:05
  • 1
    You are using a single match stage which does exactly what the find does. You need at least a project stage after that to re-shape the document. Look at array functions available there. Commented Nov 1, 2017 at 17:33

1 Answer 1

4

So after some trouble i am able to retrieve only the matched embedded document with the aggregation builder. So thanks to @Alex Bles comment i was able to think more on using aggregation functions and i found $filter array aggregation function and tried building query using that and the final query was like this:

    $qb = $dm->createAggregationBuilder('Documents\Project');
    $classObject = $qb->match()
       ->field("id", new \MongoId($projectId))
       ->project()
       ->field("classes")
       ->filter('$classes', 'class', $qb->expr()->eq('$$class._id', new \MongoId($classId)))
       ->execute()->getSingleResult();

So in the query first i matched with the _id of the project. then within that project i projected the results for the classes using the $filter array aggregation method. In the end i was able to get the embedded document filtered by their _id. Hope this will help someone in the future with same problem.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.