查询返回一条数据

@param array $query 查询条件，如：['_id' => new \MongoId('0f6821586b9887e3174e7c78')]
@param array $fields 返回的字段列表，默认全部，如：['name' => true, 'age' => true]
@param int $timeout 查询超时时间，default 2s, 0 wait forever.
@return array|null
434850
public function findOne(
        $query = [],
        $fields = [],
        $timeout = 2000
    ) {
        $this->getContext()->getLog()->profileStart($this->profileName . __FUNCTION__);
        $options = [
            'socketTimeoutMS' => $timeout
        ];
        $out = $this->mongoCollection->findOne($query, $fields, $options);
        if ($out === null) {
            return [];
        }
        $this->getContext()->getLog()->profileEnd($this->profileName . __FUNCTION__);

        return $out;
    }
1185106
public function doSearch($query = [])
    {
        if (!$this->index) {
            throw new \RuntimeException("You must set an index");
        }

        $this->prepare($query);

        // Only process query when there is a value, in order to avoid sending
        // an empty query string to ElasticSearch, its API is so weird that we
        // probably would end up with exceptions
        $value = $this->getQueryParam($query, $this->fulltextParameterName);
        if ($value) {
            $isQueryEmpty = false;

            $queryPart = [
                'query_string' => [
                    'query' => $this->fixSmartSearch((string)$value),
                    'fields' => $this->fulltextFields,
                 ],
            ];

            if ($this->fulltextAnalyzer) {
                $queryPart['query_string']['analyzer'] = $this->fulltextAnalyzer;
            }

        } else {
            $isQueryEmpty = true;
            $queryPart = [];
        }

        // This must be set before filter since filter query will be altered by
        // the applied aggregations
        $aggs = $this->buildAggQueryData($query);

        if (count($this->filterQuery)) {
            if ($isQueryEmpty) {
                $body = [
                    'query' => [
                        'constant_score' => [
                            'filter' => [
                                'fquery' => [
                                    'query' => [
                                        'query_string' => [
                                            'query' => (string)$this->filterQuery
                                        ],
                                    ],
                                    // @todo Without this ElasticSearch seems to
                                    // throw exceptions...
                                    '_cache' => true,
                                ],
                            ],
                        ],
                    ],
                ];
            } else {
                $body = [
                    'query' => [
                        'filtered' => [
                            'query'  => $queryPart,
                            'filter' => [
                                'fquery' => [
                                    'query' => [
                                        'query_string' => [
                                            'query' => (string)$this->filterQuery
                                        ],
                                    ],
                                    // @todo Without this ElasticSearch seems to
                                    // throw exceptions...
                                    '_cache' => true,
                                ],
                            ],
                        ],
                    ],
                ];
            }
        } else {
            if ($isQueryEmpty) {
                $body = [
                    'query' => [
                        'match_all' => []
                    ],
                ];
            } else {
                $body = [
                    'query' => $queryPart,
                ];
            }
        }

        if (count($this->postFilterQuery)) {
            $body['post_filter']['query_string']['query'] = (string)$this->postFilterQuery;
        }

        if ($aggs) {
            $body['aggs'] = $aggs;
        }
/*
        if ($this->fields) {
            $body['fields'] = $this->fields;
        }*/

        if (count($this->sortFields)) {
            foreach ($this->sortFields as $sort) {
                $body['sort'][] = $sort->getSortStructure();
            }
        }

        $data = [
            'index' => $this->index,
            'type'  => 'node',
            'body'  => $body,
        ];

        if (!empty($this->limit)) {
            $data['size'] = $this->limit;
            if (!empty($this->page)) {
                $data['from'] = max([0, $this->page - 1]) * $this->limit;
            }
        }

        return new Response($this, $this->client->search($data));
    }
207481
protected function parseBetween(Query $query, $key, $exp, $value, $field, $bindType)
    {
        // BETWEEN 查询
        $data = is_array($value) ? $value : explode(',', $value);

        $min = $query->bind($data[0], $bindType);
        $max = $query->bind($data[1], $bindType);

        return $key . ' ' . $exp . ' :' . $min . ' AND :' . $max . ' ';
    }
929214
protected function queryHandler($query, $bindings, $time, $connectionName)
    {
        $data = ['connectionName' => $connectionName];

        if ($this->recordSqlBindings) {
            $data['bindings'] = $bindings;
        }

        Integration::addBreadcrumb(new Breadcrumb(
            Breadcrumb::LEVEL_INFO,
            Breadcrumb::TYPE_USER,
            'sql.query',
            $query,
            $data
        ));
    }
223458
public static function first($query = null, $fields = null, $last = false)
    {
        static::applySchema();

        $key = static::getPrimaryKey();
        $table = static::getTable();
        $writer = static::getDatabase()->getWriter();

        if (!$query && !$fields) {
            $fields = '*';
        } elseif (is_string($query) && !$fields) {
            $fields = explode(',', $query);
            $query = null;
        }

        $order = '';
        if (isset($query['order'])) {
            $order = 'ORDER BY '.$query['order'];
            unset($query['order']);
        } else {
            $order = 'ORDER BY '.'`'.$key.'`'.' '.($last ? 'DESC' : 'ASC');
        }

        if (!$fields && isset($query['fields'])) {
            $fields = $query['fields'];
            unset($query['fields']);
        }

        if (!$fields) {
            $fields = '*';
        }

        $whereArray = [];
        if (isset($query['where'])) {
            if (is_array($query['where'])) {
                $query = array_merge($query, $query['where']);
            } else {
                $whereArray[] = '('.$query['where'].')';
            }
            unset($query['where']);
        }

        $valueArray = [];
        if (count($query) > 0) {
            $schema = static::getSchemaFields();
            foreach ($schema as $field) {
                if (!isset($query[$field])) {
                    continue;
                }
                $token = ':'.$field;
                $whereArray[] = "`{$field}` = {$token}";
                $valueArray[$token] = $query[$field];
            }
        }

        $join = '';
        $class = static::getClassName();
        $selectFields = $writer->selectFields($fields, $class, $join);
        $where = $writer->whereByArray($whereArray);
        $sql = "SELECT {$selectFields} FROM `{$table}` AS {$class} {$where} {$order} LIMIT 1";

        $result = static::fetch(
            $sql,
            $valueArray,
            true,
            is_array($fields) && count($fields) == 1,
            $fields == '*'
        );

        return $result;
    }
1199258
public function read($query, array $options = []) {
		$defaults = ['return' => 'resource', 'model' => $query->model()];
		$options += $defaults;
		$params = compact('query', 'options');

		return Filters::run($this, __FUNCTION__, $params, function($params) {
			$query = $params['query'];
			$params = $query->export($this);

			list($_path, $conditions) = (array) $params['conditions'];
			$model = $query->model();

			if (empty($_path)) {
				$_path = '_all_docs';
				$conditions['include_docs'] = 'true';
			}
			$path = "{$this->_config['database']}/{$_path}";
			$args = (array) $conditions + (array) $params['limit'] + (array) $params['order'];

			$result = $this->connection->get($path, $args);
			$result = is_string($result) ? json_decode($result, true) : $result;

			$data = $stats = [];

			if (isset($result['_id'])) {
				$data = [$result];
			} elseif (isset($result['rows'])) {
				$data = $result['rows'];
				unset($result['rows']);
				$stats = $result;
			}
			$stats += ['total_rows' => null, 'offset' => null];
			$opts = compact('stats') + [
				'class' => 'set', 'exists' => true, 'defaults' => false
			];

			return $this->item($model, $data, $opts);
		});
	}
1249978
protected function doFindOne(array $query, array $fields)
    {
        $mongoCollection = $this->mongoCollection;
        return $this->retry(function() use ($mongoCollection, $query, $fields) {
            return $mongoCollection->findOne($query, $fields);
        });
    }
1089439
public function timeout(): ?ObjectId
    {
        if (null === $this->current_job) {
            $this->logger->debug('reached worker timeout signal, no job is currently processing, ignore it', [
                'category' => get_class($this),
                'pm' => $this->process,
            ]);

            return null;
        }

        $this->logger->debug('received timeout signal, reschedule current processing job ['.$this->current_job['_id'].']', [
            'category' => get_class($this),
            'pm' => $this->process,
        ]);

        $this->updateJob($this->current_job, JobInterface::STATUS_TIMEOUT);

        $this->db->{$this->scheduler->getEventQueue()}->insertOne([
            'job' => $this->current_job['_id'],
            'worker' => $this->id,
            'status' => JobInterface::STATUS_TIMEOUT,
            'timestamp' => new UTCDateTime(),
        ]);

        $job = $this->current_job;

        if (0 !== $job['options']['retry']) {
            $this->logger->debug('failed job ['.$job['_id'].'] has a retry interval of ['.$job['options']['retry'].']', [
                'category' => get_class($this),
                'pm' => $this->process,
            ]);

            --$job['options']['retry'];
            $job['options']['at'] = time() + $job['options']['retry_interval'];
            $job = $this->scheduler->addJob($job['class'], $job['data'], $job['options']);

            return $job->getId();
        }
        if ($job['options']['interval'] > 0) {
            $this->logger->debug('job ['.$job['_id'].'] has an interval of ['.$job['options']['interval'].'s]', [
                'category' => get_class($this),
                'pm' => $this->process,
            ]);

            $job['options']['at'] = time() + $job['options']['interval'];
            $job = $this->scheduler->addJob($job['class'], $job['data'], $job['options']);

            return $job->getId();
        }
        if ($job['options']['interval'] <= -1) {
            $this->logger->debug('job ['.$job['_id'].'] has an endless interval', [
                'category' => get_class($this),
                'pm' => $this->process,
            ]);

            unset($job['options']['at']);
            $job = $this->scheduler->addJob($job['class'], $job['data'], $job['options']);

            return $job->getId();
        }

        $this->current_job = null;
        posix_kill($this->process, SIGTERM);

        return null;
    }
90787
public function get($appId, $query = '', $guestSpaceId = null, $totalCount = true, array $fields = null): array
    {
        $options = ['json' => ['app' => $appId, 'query' => $query]];
        if ($totalCount) {
            $options['json']['totalCount'] = $totalCount;
        }
        if ($fields) {
            $options['json']['fields'] = $fields;
        }
        /** @var JsonStream $stream */
        $stream = $this->client
            ->get(KintoneApi::generateUrl('records.json', $guestSpaceId), $options)
            ->getBody();

        return $stream->jsonSerialize();
    }
790086
protected function parseNull(Query $query, $key, $exp, $value, $field, $bindType)
    {
        // NULL 查询
        return $key . ' IS ' . $exp;
    }
596358
public function query($query, $parameters = array())
    {
        if (is_null($this->connection)) {
            return false;
        }

        try {
            if (self::$profiling) {
                $timer = $this->initProfiler();
            }

            if (!is_array($parameters)) {
                $parameters = array($parameters);
            }
            $sth = $this->connection->prepare($query);
            $sth->execute($parameters);

            if (self::$profiling && isset($timer)) {
                $this->recordQueryProfile($query, $timer);
            }
            return $sth;
        } catch (PDOException $e) {
            $message = $e->getMessage() . " In query: $query Parameters: " . var_export($parameters, true);
            throw new DbException("Error query: " . $message, (int) $e->getCode());
        }
    }
645134
public function withSearch(array $fields, array $data = [], $prefix = '')
    {
        foreach ($fields as $key => $field) {
            if ($field instanceof \Closure) {
                $field($this, isset($data[$key]) ? $data[$key] : null, $data, $prefix);
            } elseif ($this->model) {
                // 检测搜索器
                $fieldName = is_numeric($key) ? $field : $key;
                $method    = 'search' . Db::parseName($fieldName, 1) . 'Attr';

                if (method_exists($this->model, $method)) {
                    $this->model->$method($this, isset($data[$field]) ? $data[$field] : null, $data, $prefix);
                }
            }
        }

        return $this;
    }
1348370
public function value(Query $query, $field, $default = null)
    {
        $options = $query->getOptions();

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

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

        }

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

        if (is_string($field)) {
            $field = array_map('trim', explode(',', $field));
        }

        $query->setOption('field', $field);
        $query->setOption('limit', 1);

        // 生成查询SQL
        $sql = $this->builder->select($query);

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

        $query->removeOption('limit');

        $bind = $query->getBind();

        if (!empty($options['fetch_sql'])) {
            // 获取实际执行的SQL语句
            return $this->getRealSql($sql, $bind);
        }

        // 执行查询操作
        $pdo = $this->query($sql, $bind, $options['master'], true);

        $result = $pdo->fetchColumn();

        if (isset($cache) && false !== $result) {
            // 缓存数据
            $this->cacheData($key, $result, $cache);
        }

        return false !== $result ? $result : $default;
    }
67671
public function value(Query $query, $field, $default = null)
    {
        $options = $query->getOptions();
        $result  = null;
        if ($this->cache && !empty($options['cache'])) {
            // 判断查询缓存
            $cache  = $options['cache'];
            $key    = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($options));
            $result = $this->cache->get($key);
        }

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

            $query->setOption('field', $field);
            $query->setOption('limit', 1);

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

            // 执行查询操作
            $readPreference = isset($options['readPreference']) ? $options['readPreference'] : null;
            $cursor         = $this->query($options['table'], $mongoQuery, $readPreference, true, ['root' => 'array']);
            $resultSet      = $cursor->toArray();
            if (!empty($resultSet)) {
                $data = (array) array_shift($resultSet);
                if ($this->getConfig('pk_convert_id')) {
                    // 转换ObjectID 字段
                    $data['id'] = $data['_id']->__toString();
                }
                $result = $data[$field];
            } else {
                $result = null;
            }

            if (isset($cache)) {
                // 缓存数据
                $this->cacheData($key, $result, $cache);
            }
        }

        return !is_null($result) ? $result : $default;
    }
398938
public function process($query, $format = null, $timeout = 6000, $pagination = true)
    {
        $this->timeout = $timeout;
        $factory = new RequestProcessorFactory();
        $processor = $factory->create(gettype($query));
        $request = $processor->convertToObjectRequest($query);
        $validation = $this->validate($request);
        if ($validation->count() === 0) {
            $result = $this->callApi($request, $format);
            $pagination_total_result_le_pagination_item_per_page = false;
            if (isset($result->pagination)) {
                if ($result->pagination->total_result <= $result->pagination->items_per_page) {
                    $pagination_total_result_le_pagination_item_per_page = true;
                }
            }
            if ($pagination !== false ||
                $pagination_total_result_le_pagination_item_per_page) {
                return $result;
            } else {
                return $this->deletePagination($request, $format, $result);
            }
        } else {
            return $validation;
        }
    }
729111
public function command($command, $timeout = 5000)
    {
        $this->getContext()->getLog()->profileStart($this->profileName . __FUNCTION__);
        $result = $this->mongoDb->command($command, ['socketTimeoutMS' => $timeout]);
        $this->getContext()->getLog()->profileEnd($this->profileName . __FUNCTION__);
        if ($result['ok'] == 1) {
            return $result['results'];
        } else {
            $this->getContext()->getLog()->error("mongo command failed: command-" . json_encode($command) . " result-"
                . json_encode($result));

            return false;
        }
    }
1265340
public function parseFql($fieldName, $query)
    {
        // 
        if(is_string($query)) {
            // 
            $lexer = $this->createLexer((string)$query);
            
            $field = new Expr\FieldIdentifier($fieldName);
            try {
                $expr = $this->doParseExpression($lexer, $field);
            } catch(\Exception $ex) {
                throw new ParserException(sprintf('Failed to parse qeury "%s"', $query), 0, $ex);
            }

            if(!$lexer->isEol()) {
                throw new ParserException(sprintf('Invalid query "%s"', $lexer->remain()));
            }

            return $expr;
        } else if(is_array($query)) {
            $exprs = array();
            foreach($query as $q) {
                $exprs[] = $this->parseFql($fieldName, $q);
            }

            //return new Expr\AndX($exprs);
            return new Expr\LogicalExpression($exprs, Expr\LogicalExpression::TYPE_AND);
        } else {
            return new Expr\ComparisonExpression($field, $query, Expr\ComparisonExpression::EQ);
        }

        throw new ParserException('Invalid Fql query.');
    }