我在使用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获取项目,第二个条件是仅从具有特定id的嵌入文档的classes
数组中检索类。这就是我如何构建查询:
$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 PHPMongo的getDocument
方法实现类似投影,是否有可能?
更新 我尝试使用聚合框架实现,以下是查询:
$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:
答案 0 :(得分:0)
因此posting问题发生在PHPMongo GitHub问题之后,我发现到目前为止还没有实现$elemMatch
。作者在这个问题上发布了一些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
)
)
));
希望这将有助于未来的人,如果他们遇到类似我的问题,因为我试图找到解决方案而且它不在互联网上。一旦$elemMatch
的PHPMongo中有功能增强,我将尝试更新。