Doctrine MongoDB ODM - Return 仅使用查询生成器匹配嵌入式文档

Doctrine MongoDB ODM - Return only matched embedded document using query builder

我在 PHP 中使用 MongoDB ODM 查询生成器仅 return 匹配的嵌入文档时遇到问题。每个嵌入式文档都有一个在创建时生成的 MongoID。以下是我收集的文档结构 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"
        }
    ]
}

现在我只想从数据库中检索来自 classes 嵌入文档的 class符合我的标准 (即具有特定 ID 的 class。这就是我构建查询的方式:

$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();

首先我与项目 ID 匹配,然后我与嵌入文档 class ID 匹配。我期待它 return 只有 OLA 的嵌入文档,如下所示:

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

但是学说 return 整个 项目 记录(显示在问题的开头)。我还尝试使用 [=16= 进行聚合查询构建] 聚合结果仍然相同,我使用聚合生成器创建的查询如下:

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

有人可以帮我解决这个问题吗?我怎样才能构建查询以获得如上所述的期望结果。

所以在遇到一些麻烦之后,我只能使用聚合生成器检索匹配的嵌入式文档。所以感谢@ comment i was able to think more on using aggregation functions and i found $filter 数组聚合函数并尝试使用它构建查询,最终查询是这样的:

    $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();

所以在查询中我首先匹配了项目的_id。然后在该项目中,我使用 $filter 数组聚合方法投影了 classes 的结果。最后,我能够通过他们的 _id 过滤嵌入文档。希望这会帮助将来遇到同样问题的人。