1

我无法使用sokil PHPMongo ODM 库返回匹配的嵌入式文档。我是 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具有特定 id 的嵌入式文档数组中检索类。这就是我构建查询的方式:

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

    }
);

我期望它只返回OLA来自usecase-updated文档的嵌入文档,如下所示:

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

但是PHPMongo库正在返回带有所有类的整个项目文档(显示在问题的开头)。有人建议研究聚合框架。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:
4

1 回答 1

0

因此,在PHPMongo GitHub 问题上发布问题后,我发现到目前为止还没有实现. 作者就这个问题发表了一些有趣的见解,现在这个问题被标记为未来的增强。$elemMatch

此外,我尝试了聚合框架,并且成功地实现了预期的结果,我发现以下表达式的语法存在错误(完整查询,请参见上面的问题):

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

希望这将有助于将来的人们,如果他们在我尝试寻找解决方案时遇到像我这样的类似问题并且它在互联网上不存在。一旦 PHPMongo 的$elemMatch.

于 2017-11-09T11:13:03.260 回答