bardex/elastic-query

该包的最新版本(2.3.0)没有提供许可证信息。

PHP查询构建器,具有流畅的接口,用于ElasticSearch

2.3.0 2019-05-13 16:34 UTC

README

Build Status Scrutinizer Code Quality Coverage Status

要求

  • 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);
?>