我有一个包含以下结构的mongoDB文档:
{
"_id" : ObjectId("537b9731fa4634134c8b45aa"),
"kpis" : [
{
"id" : 4,
"value" : 3.78,
"entered" : Timestamp(1401377656, 9)
}
]
}
我想删除id为x的所有kpi文档。使用pull命令直接对数据库执行此操作非常简单:
db.lead.update({}, {$pull:{"kpis":{id:5}}}, {multi:true});
然而,我(几个)尝试使用doctrine ODM匹配此语法失败了:
$qb->update()
->field('kpis')
->pull($qb->expr()->field('kpis.id')->equals($kpi->getId()))
->multiple(true)
->getQuery()
->execute();
// I've also tried..
$qb->update()
->field('kpis')
->pull($qb->expr()->field('kpis')->elemMatch(
$qb->expr()->field('kpis.id')->equals($kpi->getId())
))
->multiple(true)
->getQuery()
->execute();
什么都没有删除。我正确使用查询构建器吗?
答案 0 :(得分:4)
我相信你想要做以下事情:
$qb->update()
->field('kpis')->pull(array('id' => $kpi->getId()))
->multiple(true)
->getQuery()
->execute();
您可以使用Query::debug()
方法转储由此生成的实际查询。您应该在转储的newObj
字段中预期以下内容:
{ "$pull": { "kpis": { "id": <number> }}}
解释为什么您之前的示例不起作用:
->field('kpis')
->pull($qb->expr()->field('kpis.id')->equals($kpi->getId()))
在这里,您要创建以下查询:
{ "$pull": { "kpis": { "kpis.id": <number> }}}
这只会匹配:
kpis
数组中的每个嵌入对象都有一个嵌入的kpis
对象,则该对象的id
字段与该数字相匹配。kpis
数组中的嵌入对象有自己的kpis
数组,其中包含匹配的id
字段的嵌入对象。这将是MongoDB的array element matching开始发挥作用。在你的第二个例子中,你有:
->field('kpis')
->pull($qb->expr()->field('kpis')->elemMatch(
$qb->expr()->field('kpis.id')->equals($kpi->getId())
))
这将生成以下查询:
{ "$pull": { "kpis": { "$elemMatch": { "kpis.id": <number> }}}}
我以前从未见过这样的语法,但我认为$elemMatch
是超级的,因为$pull
已经采用标准来匹配数组元素作为其参数。当您在数组字段上直接匹配时,$elemMatch
在查询中非常有用,并不意味着对数组元素进行完全相等匹配(即您想要提供标准而不是精确匹配)。