• Welcome to Journal web site.

我是 PHP 程序员

- 开发无止境 -

Next
Prev

tp6 mongodb遇到的问题整理

Data: 2023-01-16 23:42:18Form: JournalClick: 1

使用tp6的value()和column()查询遇到报错

column(‘name’)直接传参报错

Expected “projection” option to be array or object, string given

因为options里的projection是字符串,所以报错,改成数组

Call to undefined method think\db\connector\Mongo::query()

追溯到文件发现$this->query 是null

更新解决方法
最后发现是tp6用composer下载的mongodb库有问题,对比tp6自带的代码将图示位置改掉就好了

原本代码为

$options = $query->parseOptions();

        if (isset($options['projection'])) {
            $query->removeOption('projection');
        }

        if ($key && '*' != $field) {
            $projection = $key . ',' . $field;
        } else {
            $projection = $field;
        }

        $query->setOption('projection', $projection);

        if (!empty($options['cache'])) {
            // 判断查询缓存
            $cacheItem = $this->parseCache($query, $options['cache']);
            $result    = $this->getCacheData($cacheItem);

            if (false !== $result) {
                return $result;
            }
        }

        $mongoQuery = $this->builder->select($query);

        if (isset($options['projection'])) {
            $query->setOption('projection', $options['projection']);
        } else {
            $query->removeOption('projection');
        }

        // 执行查询操作
        $readPreference = $options['readPreference'] ?? null;
        $resultSet      = $this->query($options['table'], $mongoQuery, $readPreference);
 

修改后

        $options = $query->parseOptions();

        if (isset($options['projection'])) {
            $query->removeOption('projection');
        }
		
		if (is_array($field)) {
		    $field = implode(',', $field);
		}
        if ($key && '*' != $field) {
            $projection = $key . ',' . $field;
        } else {
            $projection = $field;
        }

        $query->field($projection);

        if (!empty($options['cache'])) {
            // 判断查询缓存
            $cacheItem = $this->parseCache($query, $options['cache']);
            $result    = $this->getCacheData($cacheItem);

            if (false !== $result) {
                return $result;
            }
        }

        $mongoQuery = $this->builder->select($query);
 

value()方法报错原因


这个位置不可以直接强制把string类型的字段名直接转成数组。

		//需要改成 $field => 1 的格式来查询 代表着只查询这个字段,
		//同理  这里也可以 [$field1 => 1, $field2 => 1, $field3 => 1] 代表查询指定的三个字段
		//或者  [$field => 0] 代表查询除$field外的所有字段
        $query->setOption('projection', [$field => 1]);
 

group的方法

**

转载自https://www.jianshu.com/p/151d20e32707

**

找到/vendor/topthink/think-mongo/src/builder/Mongo.php 这个文件
将multiAggregate方法 进行修改

    /**
     * 多聚合查询命令, 可以对多个字段进行 group by 操作
     *
     * @param Query     $query  查询对象
     * @param array     $extra 指令和字段
     * @return Command
     */
    public function multiAggregate(Query $query, $extra)
    {
        $options = $query->getOptions();

		list($aggregate, $groupBy) = $extra;

        $groups = ['_id' => []];

        foreach ($groupBy as $field) {
            $groups['_id'][$field] = '$' . $field;
        }
		
        foreach ($aggregate as $fun => $field) {
			$groups[$fun . '_' . $field] = ['$' . $fun => $field];
        }

        $pipeline = [
            ['$match' => (object) $this->parseWhere($query, $options['where'])],
            ['$group' => $groups],
        ];

        $cmd = [
            'aggregate'    => $options['table'],
            'allowDiskUse' => true,
            'pipeline'     => $pipeline,
            'cursor'       => new \stdClass,
        ];

        foreach (['explain', 'collation', 'bypassDocumentValidation', 'readConcern'] as $option) {
            if (isset($options[$option])) {
                $cmd[$option] = $options[$option];
            }
        }

        $command = new Command($cmd);
        $this->log('group', $cmd);

        return $command;
    }
 

后续想了一下,这个写法 如果字段是int类型是没问题的 但是没法用sum:1来统计总数

Name:
<提交>