bardex / elastic-query
PHP查询构建器,具有流畅的接口,用于ElasticSearch
Requires
- php: >=5.5.0
- elasticsearch/elasticsearch: ~2.0|~5.0
- psr/log: ~1.0
Requires (Dev)
- phpunit/phpunit: 4.8.*
README
要求
- PHP >= 5.5
- PHP Elasticsearch\Client ~2.0 或 ~5.0(仅限PHP >= 5.6.6)
- ElasticSearch服务器 >= 5.0
安装
$ composer require bardex/elastic-query
快速开始
<?php use Bardex\Elastic\Client; // 1. Create client: $client = Client::create('localhost'); // OR $elastic = \Elasticsearch\ClientBuilder::create() ->setHosts(['localhost']) ->build(); $client = new Client($elastic); // 2. Create search query // this is instance of \Bardex\Elastic\SearchQuery $query = $client->createSearchQuery(); $query->setIndex('shop', 'products') ->where('rubric')->in([1,5,7]) ->where('price')->greater(0) ->where(['title','anons'])->match('game') ->exclude(['anons', 'comments']) // exclude fields ->setOrderBy('rating', 'desc') ->addOrderBy('dateCreation', 'desc') ->limit(30, 0); // this is instance of \Bardex\Elastic\SearchResult $results = $query->fetchAll(); // count of fetched results $countResults = count($results); // count of total found results $totalFound = $results->getTotalFound(); // iterate results foreach ($results as $result) { echo $result['id'] . ':' . $result['title'] . '<br>'; } //Fetch one column as array $result->fetchColumn('id'); // ex. return [1,2,3] or [] // get first result (or null if empty) $first = $results->getFirst(); // nothing found ? $results->isEmpty(); ?>
使用多查询
您可以使用MultiQuery在单个请求中对服务器执行多个搜索查询。https://elastic.ac.cn/guide/en/elasticsearch/reference/current/search-multi-search.html
<?php use Bardex\Elastic\Client; $client = Client::create('localhost'); $postsQuery = $client->createSearchQuery() ->setIndex('blog', 'posts') ->where('userId')->equal(1) ->where('status')->equal('published') ->setOrderBy('dateCreation', 'desc') ->limit(10, 0); $userQuery = $client->createSearchQuery() ->setIndex('blog', 'users') ->where('id')->equal(1); $results = $client->createMultiQuery() ->addQuery('posts', $postsQuery) ->addQuery('user', $userQuery) ->fetchAll(); $user = $results['user']; $posts = $results['posts']; $totalPosts = $posts->getTotalFound(); // OR $multi = $client->createMultiQuery(); $multi->createSearchQuery('posts') ->setIndex('blog', 'posts') ->where('userId')->equal(1) ->where('status')->equal('published') ->setOrderBy('dateCreation', 'desc') ->limit(10, 0); $multi->createSearchQuery('user') ->setIndex('blog', 'users') ->where('id')->equal(1); $results = $multi->fetchAll(); $user = $results['user']; $posts = $results['posts']; ?>
使用监听器进行日志记录
<?php use Bardex\Elastic\Client; $client = Client::create('localhost'); // some logger implemented \Psr\Log\LoggerInterface, like Monolog. $logger = new Logger; $logger->setFacility('elastic-query'); $log = new \Bardex\Elastic\Listener\Logger($logger); $log->setLogAllQueries(true); // debug log-level $log->setLogErrorQueries(true); // error log-level $log->setLogSlowQueries(true); // warning log-level $log->setSlowQueryLimitMs(100); $client->addListener($log); ?>
使用自定义的Hydrator
<?php use Bardex\Elastic\Client; $client = Client::create('localhost'); // hydrator must implements interface \Bardex\Elastic\IHydrator or extends \Bardex\Elastic\Hydrator $hydrator = new CustomHydrator; $client->setHydrator($hydrator); ?>
可用的过滤方法(在SearchQuery中)
-
equal($value)
-
in([$v1,$v2,...])
-
less($max)
-
lessOrEqual($max)
-
greater($min)
-
greaterOrEqual($min)
-
between($min, $max)
-
match($text, $operator = 'or') - 全文搜索
-
wildcard('rosy*')
-
regexp('ro.*n')
-
less($dateEnd, $dateFormat)
-
lessOrEqual($dateEnd, $dateFormat)
-
greater($dateStart, $dateFormat)
-
greaterOrEqual($dateStart, $dateFormat)
-
between($start, $end, $dateFormat)
-
exists() - 字段存在且不为空
-
not($value) - 不相等
-
notIn([$v1,$v2,...])
-
notBetween($min, $max)
-
notMatch($text) - 文本不匹配
-
notExists() - 字段不存在或为空
-
minScore() - 通过最小分数过滤
另请参阅类 \Bardex\Elastic\Where。
日期格式请参阅https://elastic.ac.cn/guide/en/elasticsearch/reference/5.0/mapping-date-format.html
存在过滤器https://elastic.ac.cn/guide/en/elasticsearch/reference/5.0/query-dsl-exists-query.html
示例
<?php $query->where('id')->equal(10) ->where('category')->in([1,5,3]) ->where(['title','anons'])->match('game') // full-text search by multi fields ->where('price')->between(100,1000) // min and max values included ->where('date_creation')->greater('2017-01-31T23:00:00+03:00', 'date_time_no_millis') ->where('refunds')->notExists() ->minScore(0.1); ?>
搜索上下文
匹配其他查询的布尔组合的文档的查询。它使用一个或多个布尔子句构建,每个子句都有一个类型化出现。出现类型是
- must - 子句(查询)必须在匹配的文档中出现,并将有助于评分。
- filter - 子句(查询)必须在匹配的文档中出现。然而,与must不同,查询的评分将被忽略。过滤子句在过滤上下文中执行,这意味着评分被忽略,子句被视为缓存。
- should - 子句(查询)应在匹配的文档中出现。如果bool查询处于查询上下文并且有一个must或filter子句,则即使没有should查询匹配,文档也将匹配bool查询。在这种情况下,这些子句仅用于影响评分。如果bool查询是过滤上下文或没有must或filter,则至少有一个should查询必须匹配文档才能使bool查询匹配。
默认使用 must 上下文。
另请参阅https://elastic.ac.cn/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
示例
<?php use Bardex\Elastic\Query; $query->where('id')->equal(10) ->where('category', Query::CONTEXT_FILTER)->equal(1) ->where('status', Query::CONTEXT_FILTER)->equal('published') ->where('title', Query::CONTEXT_SHOULD)->match('game') ->where('tags', Query::CONTEXT_SHOULD)->in(['game', 'gamebox']) ->setOrderBy(Query::ORDER_BY_SCORE, 'desc'); ?>
检索指定字段
select()和exclude()方法可以一起使用。
<?php $query->select(['id', 'title', 'comments.*', 'categories.*']) ->exclude(['description', '*.description']); ?>
限制检索文档
<?php $query->limit($limit, $offset); ?>
对文档进行排序
<?php $query->setOrderBy('date_creation', 'desc'); // clear old order and set new order $query->addOrderBy('rating', 'desc'); // add order ?>
使用脚本字段
另请参阅https://elastic.ac.cn/guide/en/elasticsearch/reference/current/search-request-script-fields.html
方法 searchQuery::fetchAll() 合并脚本字段与文档字段。
<?php // script return scalar $script = new \Bardex\Elastic\Script(); $script->addLine('def a = 100;'); $script->addLine('return a;'); // return scalar $query->addScriptField('fieldName', $script); $result = $query->fetchAll()->getFirst(); echo $result['fieldName']; // 100 // script return array $script = new \Bardex\Elastic\Script(); $script->addLine('def a = 100;'); $script->addLine('def b = 200;'); $script->addLine('return [a,b];'); // return array $query->addScriptField('fieldName', $script); $result = $query->fetchAll()->getFirst(); print_r($result['fieldName']); // [100, 200] ?>
使用文档值和脚本参数。
也请参阅
https://elastic.ac.cn/guide/en/elasticsearch/reference/current/modules-scripting-expression.html
<?php $script = new Script(); $script->addLine("return doc['id'].value * params.power;"); $script->addParam('power', 1000); $query->addScriptField('pid', $script); $row = $query->fetchAll()->getFirst(); echo $row['id']; // 2 echo $row['pid']; // 2000 ?>
使用脚本过滤器
也请参阅 https://elastic.ac.cn/guide/en/elasticsearch/reference/current/query-dsl-script-query.html
<?php $script = new Script(); $script->addLine("return doc['price'].value * (1 + doc['tax'].value / 100) < params.max_price;"); $script->addParam('max_price', 10000); $query->whereScript($script); $rows = $query->fetchAll(); ?>
调试
获取准备好的Elasticsearch查询作为PHP数组
<?php $query->getQuery(); ?>
获取来自ElasticSearch服务器的原始响应
<?php $query->fetchAll(false); ?>