Doctrine MongoDB ODM - 使用查询构建器

时间:2017-11-01 16:29:51

标签: php mongodb doctrine doctrine-odm doctrine-query

我在使用PHP中的MongoDB ODM查询构建器返回匹配的嵌入式文档时遇到了麻烦。每个嵌入的文档都有一个创建时生成的MongoID。以下是我的文档结构项目

{ 
    "_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"
        }
    ]
}

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

$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然后我匹配嵌入的文档类id。我希望它只返回 OLA 的嵌入式文档,如下所示:

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

但是,学说正在返回整个项目记录(显示在问题的开头)。我也尝试使用$match聚合构建聚合查询,结果仍然与查询相同使用聚合构建器创建的内容如下:

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

有人可以帮我解决这个问题吗?如何构建我得到所需结果的查询,如上所述。

1 个答案:

答案 0 :(得分:0)

因此,在遇到麻烦之后,我只能使用聚合构建器检索匹配的嵌入式文档。所以感谢@ Alex Bles评论,我能够更多地考虑使用聚合函数,我找到$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过滤嵌入的文档。希望这将有助于未来有同样问题的人。