使用Doctrine ODM从mongodb文档中的数组中删除项目

Lee*_*vis 2 php doctrine mongodb doctrine-odm

我有一个包含以下结构的mongoDB文档:

{
        "_id" : ObjectId("537b9731fa4634134c8b45aa"),
        "kpis" : [
                {
                        "id" : 4,
                        "value" : 3.78,
                        "entered" : Timestamp(1401377656, 9)
                }
        ]
}
Run Code Online (Sandbox Code Playgroud)

我想删除ID为x的所有kpi文档。使用pull命令直接在数据库上执行此操作非常简单:

db.lead.update({}, {$pull:{"kpis":{id:5}}}, {multi:true});
Run Code Online (Sandbox Code Playgroud)

但是,我(几次)尝试使用教义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();
Run Code Online (Sandbox Code Playgroud)

什么都没有删除。我是否正确使用查询生成器?

jmi*_*ola 5

我相信您要执行以下操作:

$qb->update()
    ->field('kpis')->pull(array('id' => $kpi->getId()))
    ->multiple(true)
    ->getQuery()
    ->execute();
Run Code Online (Sandbox Code Playgroud)

您可以使用该Query::debug()方法转储由此生成的实际查询。您应该在转储newObj字段中期望以下内容:

{ "$pull": { "kpis": { "id": <number> }}}
Run Code Online (Sandbox Code Playgroud)

要解释为什么前面的示例不起作用:

->field('kpis')
->pull($qb->expr()->field('kpis.id')->equals($kpi->getId()))
Run Code Online (Sandbox Code Playgroud)

在这里,您正在创建以下查询:

{ "$pull": { "kpis": { "kpis.id": <number> }}}
Run Code Online (Sandbox Code Playgroud)

这只会匹配:

  1. 如果顶级kpis数组中的每个嵌入式对象中都有一个嵌入式kpis对象,则该嵌入式对象又具有id与数字匹配的字段。
  2. 如果顶级数组中的嵌入式对象具有kpis自己的kpis数组,该数组由具有id匹配字段的嵌入式对象组成。这将是MongoDB的数组元素匹配起作用。

在第二个示例中,您具有:

->field('kpis')
->pull($qb->expr()->field('kpis')->elemMatch(
    $qb->expr()->field('kpis.id')->equals($kpi->getId())
))
Run Code Online (Sandbox Code Playgroud)

这将生成以下查询:

{ "$pull": { "kpis": { "$elemMatch": { "kpis.id": <number> }}}}
Run Code Online (Sandbox Code Playgroud)

我以前从未见过这样的语法,但是我认为它$elemMatch是多余的,因为$pull已经采用匹配数组元素的条件作为其参数。$elemMatch当您直接在数组字段上进行匹配而不是要对数组元素进行完全相等匹配时(即您提供条件而不是完全匹配),在查询中很有用。