PHP / MongoDB - $ concat aggregation

时间:2017-10-19 22:25:42

标签: php mongodb mongodb-query aggregation-framework

我有以下功能:

public function cmd(Array $cmd){
    if ($this->ready_to_act()){
        $comando = [
            'aggregate' => $this->collection,
            'pipeline' => [
                [
                    '$concat'=>[
                        'final_value'=>[
                            '$first',
                            ' ',
                            '$last'
                        ]
                    ]
                ],
                [
                    '$match'=>[
                        'final_value'=> new MongoDB\BSON\Regex("/$texto/",'gi')
                    ]
                ]
            ]
        ];
        $command = new MongoDB\Driver\Command($cmd);
        return $this->link
                    ->executeCommand($this->database,$command);
    }else{
        throw new MongoDB\Driver\Exception\InvalidArgumentException("No hay base de datos/coleccion definida!");
        die();
    }
}

我正在尝试运行一个连接第一个最后 “列”的命令,并检查最终值就像 $ texto

但是出了点问题。在PHP文档中没有关于$ concat的内容。

  

无法识别的管道阶段名称:'$ concat'

我不知道该怎么做,我在做什么错误

对我来说,不允许使用Composer。

1 个答案:

答案 0 :(得分:1)

错误的驱动程序

如上所述,您使用错误的驱动程序开始。因此,首先要做的是安装正确的驱动程序documented。如果您仍然对哪个驱动程序是哪个感到困惑,那么这个page on php.net会有一个图解释所有。

您确实应该安装并使用正确的驱动程序,因为这是打算在应用程序空间中使用的驱动程序。您目前拥有的低级接口适用于已经知道他们正在做什么的驱动程序软件开发人员,并且正在以非常低的价格实现框架的集成功能 水平。

正确的管道

虽然因为$concat不是"管道阶段"而引发了基本错误。它是在$project$addFields等管道阶段内使用的运算符,这就是您在此上下文中使用它的方式:

$pipeline = [
  [ '$addFields' => [
    'final_value' => [
      '$concat' => [ '$first', ' ', '$last' ]
    ]
  ]],
  [ '$match'=>[
    'final_value'=> new MongoDB\BSON\Regex("/$texto/",'gi')
  ]]
];

这是定义管道的正确方法。如果您没有$addFields(来自MongoDB 3.2,它应该是minimal version you have installed by now 注意),那么您使用$project并定义&#34 ;所有"您希望另外收到的文档属性。

作为一个琐事,如果你有MongoDB 3.4那么你可以"可以"在$indexOfCP管道阶段中使用$redact代替:

$pipeline = [
  [ '$redact' => [
    '$cond' => [
      'if' => [
        '$ne' => [
          [ '$indexOfCP' => [
            [ '$concat' => [ '$first', ' ', '$last' ] ],
            $texto
          ]],
          -1
        ]
      ],
      'then' => '$$KEEP',
      'else' => '$$PRUNE'
    ]
  ]]
];

但是我真的不认为你应该这样做或者你正在尝试更正的聚合管道,因为有一个更好的方法来处理MongoDB。当然,pipeline表达式确实应该通过使用来发布  MongoDB\Collection::aggregate()在正确的驱动程序命名空间中。

替代

老实说,你真的应该在这里使用$text搜索。这允许您在两个字段上定义"text index",然后您只需输入查询的搜索词。

假设数据库名称空间为"test"且名为"collection"的集合,您可以创建索引:

$collection = (new MongoDB\Client)->test->collection;
$indexName = $collection->createIndex(['first' => 'text', 'last' => 'text' ])

然后发出查询:

$collection = (new MongoDB\Client)->test->collection;

$cursor = $collection->find([
  '$text' => [ '$search' => $words_or_phrase ]
]);

foreach ($cursor as $document) {
  var_dump($document);  # do something real here
}

所以"查询"不需要知道要搜索哪些属性,因为这些是在创建索引时定义的。你只需输入"单词"名称,作为第一个或最后一个或两个,并且将返回匹配,以及与匹配相关的顺序,因为这是文本搜索所做的。

但是,你真的需要使用正确的驱动程序,它非常乐意返回正确的光标并以标准方式支持所有其他选项。

  

注意:截至2018年2月,3.2之前的MongoDB版本的官方支持到期。请参阅Support Policy