PHPMongo - 仅在 MongoDB 中查找并返回匹配的嵌入文档

PHPMongo - Find and Returned only Matched embedded document in MongoDB

我在使用 sokil PHPMongo ODM 库 return 匹配嵌入文档时遇到问题。我是 ODM 概念的新手,以下是我的集合项目的文档结构:

{ 
    "_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 的项目,第二个条件是从具有特定 [=] 的嵌入文档数组 classes 中仅检索 class 46=] 是我构建查询的方式:

$collection = $PHPMongoDBInstance->getCollection("Project");



  $result = $collection->getDocument(
    "59f889e46803fa3713454b5d",
    function (\Sokil\Mongo\Cursor $cursor) {
        // get embedded documents with matched id
        $cursor->whereElemMatch("classes", $cursor->expression()->where("_id", new MongoId("59f9d7776803faea30b895dd")));

    }
);

我原以为 return 只有 OLA 的嵌入文档来自 usecase-updated 文档,如下所示:

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

但是 PHPMongo 库正在 return 包含所有 class 的整个项目文档(显示在问题的开头)。有人建议研究聚合框架。但问题是 PHPMongo 上没有足够好的文档来使用数组聚合函数(如 $filter

我尝试使用 MongoCollection 的本机实例,然后我可以使用 findOne 方法以这种方式投影我的最终结果:

$result = $collection->getMongoCollection("Project")->
             findOne(array("_id" => new MongoId("59f889e46803fa3713454b5d")), 
             array("classes" => 
                    array('$elemMatch' => 
                           array("_id" => new MongoId("59f9d7776803faea30b895dd")))));

如果我想使用 sokil PHPMongogetDocument 方法实现类似的投影,有没有可能?

更新: 我尝试使用聚合框架实现,以下是查询:

$result = $collection->aggregate(array(
    array(
        '$match' => array(
            "_id" => new MongoId("59f889e46803fa3713454b5d")
        )
    ),
    array(
        '$project' => array(
            'classes' => array(
                '$filter' => array(
                    'input' => '$classes',
                    'as' => 'classItem',
                    'cond' => array(
                        '$eq' => array('$$classItem._id' => new MongoId("59f9d7776803faea30b895dd"))
                    )
                )

            )

        )
    )

));

但我得到这个例外:

Sokil\Mongo\Exception\nMessage: Aggregate error: Unrecognized expression '$$classItem._id'\nFile:

所以在 posting the problem on the PHPMongo GitHub issues i found so far there is no implementation of $elemMatch. Author posted some interesting insights 这个问题之后,现在这个问题被标记为未来的增强。

此外,我已经尝试过聚合框架并且我能够成功地达到预期的结果我发现以下表达式的语法有错误(完整查询见上面的问题):

'$eq' => array('$$classItem._id' => new MongoId("59f9d7776803faea30b895dd"))

我了解到 '$eq' 的表达式不应该是一个关联数组,而表达式中的每个元素应该是一个单独的数组项,如下所示:

'$eq' => array('$$class._id', new MongoId("59f9d7776803faea30b895dd"))

所以现在我的最终聚合查询是这样的:

$collection = $PHPMongoDBInstance->getCollection("Project");
$result = $collection->aggregate(array(
    array(
        '$match' => array(
            "_id" => new MongoId('59f889e46803fa3713454b5d')
        )
    ),
    array(
        '$project' => array(
            'classes' => array(
                '$filter' => array(
                    'input' => '$classes',
                    'as' => 'class',
                    'cond' => array(
                        '$eq' => array('$$class._id', new MongoId("59f9d7776803faea30b895dd"))
                    )
                )
            ),
            'projectName' => 1
        )
    )
));

希望这会在将来帮助人们,如果他们遇到像我一样的类似问题,因为我试图找到解决方案,但它不存在于 Internet 上。一旦 $elemMatch.

的 PHPMongo 功能增强,我将尝试更新