【问题标题】:Translate MongoDB Aggregation $all (JS) into Doctrine ODM Aggregation (PHP)将 MongoDB Aggregation $all (JS) 翻译成 Doctrine ODM Aggregation (PHP)
【发布时间】:2019-04-15 08:50:05
【问题描述】:

我目前正在尝试转换此 JS 代码:

db.Issue.aggregate( [
  { // Filter out issues that have been worked on after our given week = All worklogs muste have been before date
      $match : { 
          worklogs: { $all: [
            { 
                "$elemMatch" : {
                    date: { $lte: endDate }
                }    
            },
          ] }
      }
  }
] )

(根据官方文档:Use $all with $elemMatch

使用他们的聚合构建器进入 Doctrine ODM 代码:

$builder = $this->createAggregationBuilder();

$aggregation = $builder
    ->match()
        ->field('worklogs')
        ->all([
            $builder->matchExpr()->elemMatch(
               $builder->expr()->field('date')->lte($week->getEndDate())
               )
       ])
;

但是,显然我无法正确匹配 $all - 这意味着我可以确保集合中的所有条目都满足 $elemMatch 检查的要求。

JS 中的原始 MongoDB 查询似乎可以解决问题,但我无法在 PHP 中接收相同的结果。到目前为止,我什至不确定 Doctrine 是否可以处理 $all$elemMatch 的组合。

更新:

到目前为止,感谢大家的 cmets!然而,我仍在为$not / ->not() 运算符的当前查询语法(在 PHP 中!)苦苦挣扎。我已经在这里检查了文档:Doctrine ODM Docs,但找不到任何有用的东西。 (另请注意,我在这里使用的是 2.0 版)。

现在我的查询看起来像:

->match()
    ->field('worklogs')
        ->not([
            $builder->matchExpr()->elemMatch(
                $builder->matchExpr()->field('date')->gt($week->getEndDate())
            )
        ])

但是会导致这个错误:

1) App\Tests\Repository\IssueRepositoryTest::testGetEstimationsPerWeek MongoDB\Driver\Exception\CommandException:$ 不需要正则表达式或文档 /var/www/html/vendor/mongodb/mongodb/src/Operation/Aggregate.php:263 /var/www/html/vendor/mongodb/mongodb/src/Collection.php:223 /var/www/html/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php:168 /var/www/html/vendor/doctrine/mongodb-odm/lib/Doctrine/ODM/MongoDB/Aggregation/Stage.php:35 /var/www/html/src/Repository/IssueRepository.php:85

【问题讨论】:

  • 只是一个 PHP 翻译错误。这实际上是->all([ [$builder->.... ] ]),注意额外的[]。只是 singular [] (正如你所拥有的)在翻译中意味着{},所以你想要[ { ... } ],因此在老话中需要额外的[]array()
  • 在这种特殊情况下,您既不需要 $all 也不需要 $elemMatch。 {$match: {"worklogs.date": {$lte: endDate}}} 完全一样。
  • @AlexBlex 会不会也匹配集合中只有一个条目满足要求的结果?而我想要一个匹配所有元素的查询?
  • 数组中只有 1 个 $elemMatch,所以它是 ALL 的 1 个元素。我认为您误解了 $all 的作用。如果您已经阅读了问题中发布的链接后面的页面,请滚动到顶部并重新阅读,注意每个单词。 mongodb 中的“集合”也用于指代文档集合 - 在您的情况下,“问题”是一个集合。 “工作日志”不是一个集合,而是一个文档、子文档或嵌入文档的数组。请遵守术语以避免混淆。
  • 这两种形式实际上都不返回数组中的 ALL 元素 与条件匹配的位置。如果这就是您想要的,您实际上会将条件 反转$gt 并使用 $not。即"worklogs": { "$not": { "$elemMatch": { "date": { "$gt": endDate } } } }。您在文档中指向的$all 示例实际上适用于“多个条件”,而不是您假设的“所有数组元素”。

标签: php mongodb doctrine doctrine-odm


【解决方案1】:

感谢@neil-lunn 的帮助,我能够找出正确的查询:

->match()
    ->field('worklogs')
        ->not(
            $builder->matchExpr()->elemMatch(
                $builder->matchExpr()->field('date')->gt($week->getEndDate())
            )
        )

【讨论】:

    猜你喜欢
    • 2020-05-19
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 1970-01-01
    • 2021-04-10
    • 2015-07-23
    相关资源
    最近更新 更多