- guzzlehttp/guzzle
- elasticsearch/elasticsearch
- laravel/scout
- babenkoivan/scout-elasticsearch-driver
- predis/predis 資料量大需要使用佇列同步、拉取資料時安裝
1.安裝 guzzlehttp/guzzle
composer require guzzlehttp/guzzle
在 app/Services 目錄下編寫 Http 服務類
<?php
namespace App\Services;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
class HttpService
{
protected $client;
public function __construct()
{
$this->client = new Client(['verify' => false, 'timeout' => 0,]);
}
/**
* 傳送 get 請求
* @param $url
* @param array $aQueryParam
* @param string $isDecode
* [@return](https://learnku.com/users/31554) mixed
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function get($url, $aQueryParam = [], $isDecode = true)
{
$response = $this->client->request('GET',
$url,
[
'query' => $aQueryParam
]);
if($isDecode){
return \GuzzleHttp\json_decode($response->getbody()->getContents(), true);
}
return $response->getbody()->getContents();
}
/**
* 傳送 post 請求
* @param $url
* @param array $aParam
* @param string $type
* @param string $isDecode
* [@return](https://learnku.com/users/31554) mixed
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function post($url, $aParam = [], $type = 'form_params', $isDecode = true)
{
$aOptions = [];
// Sending application/x-www-form-urlencoded POST
if ($type == 'form_params') {
$aOptions['form_params'] = $aParam;
}
// upload JSON data
if ($type == 'json') {
$aOptions['json'] = $aParam;
}
$response = $this->client->request('POST', $url, $aOptions);
if($isDecode){
return \GuzzleHttp\json_decode($response->getbody()->getContents(), true);
}
return $response->getbody()->getContents();
}
/**
* 傳送 put 請求
* @param $url
* @param array $aParam
* @param string $type
* @param string $isDecode
* [@return](https://learnku.com/users/31554) mixed
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function put($url, $aParam = [], $type = 'form_params', $isDecode = true)
{
$aOptions = [];
// Sending application/x-www-form-urlencoded POST
if ($type == 'form_params') {
$aOptions['form_params'] = $aParam;
}
// upload JSON data
if ($type == 'json') {
$aOptions['json'] = $aParam;
}
$response = $this->client->request('PUT', $url, $aOptions);
if($isDecode){
return \GuzzleHttp\json_decode($response->getbody()->getContents(), true);
}
return $response->getbody()->getContents();
}
/**
* 儲存遠端檔案到本地
* 跟隨第三方伺服器url重定向
* @param $url
* [@return](https://learnku.com/users/31554) bool|string
*/
public function getRemoteFile($url)
{
$jar = new CookieJar();
$aOptions = ['cookies' => $jar];
$response = $this->client->request('GET', $url, $aOptions);
return $response->getBody()->getContents();
}
}
2.安裝 elasticsearch/elasticsearch
composer require elasticsearch/elasticsearch
3.安裝 laravel/scout
composer require laravel/scout
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
4.安裝 scout 第三方驅動 babenkoivan/scout-elasticsearch-driver
composer require babenkoivan/scout-elasticsearch-driver
php artisan vendor:publish --provider="ScoutElastic\ScoutElasticServiceProvider"
scout 服務配置,在 env 中增加配置項
// 驅動的host,若需賬密:http://es_username:password@127.0.0.1:9200
SCOUT_ELASTIC_HOST=elasticsearch:9200
// 驅動
SCOUT_DRIVER=elastic
// 佇列配置,資料量大時建議開啟
SCOUT_QUEUE=true
5.安裝 predis/predis
composer require predis/predis
初始化 elatic Template
這裡以 artisan 命令的方式配置 生成命令檔案
php artisan make:command EsInit
<?php namespace App\Console\Commands; use App\Services\HttpService; use Illuminate\Console\Command; class EsInit extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'es:init'; /** * The console command description. * * @var string */ protected $description = 'init laravel es for article'; /** * Create a new command instance. * * [@return](https://learnku.com/users/31554) void */ protected $http; public function __construct() { parent::__construct(); parent::__construct(); $this->http = new HttpService(); } /** * Execute the console command. * * [@return](https://learnku.com/users/31554) mixed */ public function handle() { $this->createTemplate(); } protected function createTemplate() { $aData = [ /* * 這句是取在scout.php(scout是驅動)裡我們配置好elasticsearch引擎的index項。 * PS:其實都是取陣列項,scout本身就是return一個陣列, * scout.elasticsearch.index就是取 * scout[elasticsearch][index] * */ 'template'=>config('scout.elasticsearch.index'), 'mappings'=>[ 'articles' => [ 'properties' => [ 'title' => [ 'type' => 'text' ], 'content' => [ 'type' => 'text' ], 'created_at' => [ 'format' => 'yy-MM-dd HHss', 'type' => 'date' ], 'updated_at' => [ 'format' => 'yy-MM-dd HHss', 'type' => 'date' ] ] ] ], ]; $url = config('scout.elasticsearch.hosts')[0] . '/' . '_template/rtf'; $this->http->put($url,$aData,'json'); } }
生成檢索 model
php artisan make:model Models/Article
建立 model 索引配置檔案
- Elasticsearch\ArticleIndexConfigurator.php
<?php namespace App\Elasticsearch; use ScoutElastic\IndexConfigurator; use ScoutElastic\Migratable; class ArticleIndexConfigurator extends IndexConfigurator { use Migratable; protected $name = 'articles'; /** * @var array */ protected $settings = [ 'analysis' => [ 'analyzer' => [ 'es_std' => [ 'type' => 'standard', 'stopwords' => '_spanish_' ] ] ] ]; }
建立 model 檢索規則檔案
Elasticsearch\SearchRules\ArticleRule.php
<?php namespace App\Elasticsearch\SearchRules; use ScoutElastic\SearchRule; class ArticleRule extends SearchRule { /* * @inheritdoc */ public function buildHighlightPayload() { return [ 'fields' => [ 'title' => [ 'type' => 'unified', ], 'content' => [ 'type' => 'unified', ], ] ]; } //進行 match 搜尋,會分詞 public function buildQueryPayload() { $query = $this->builder->query; return [ 'must' => [ 'query_string' => [ 'query' => $query, ], ], ]; } }
設定 model Mapping 及檢索欄位
class Article extends Model
{
protected $indexConfigurator = ArticleIndexConfigurator::class;
use Searchable;
/**
* 檢索規則
* @var string[]
*/
protected $searchRules = [
ArticleRule::class
];
// 設定模型欄位的對映關係
protected $mapping = [
'properties' => [
'id' => [
'type' => 'integer',
],
'title' => [
'type' => 'text',
'analyzer' => 'ik_max_word',
'search_analyzer' => 'ik_max_word',
'index_options' => 'offsets',
'store' => true
],
'content' => [
'type' => 'text',
'analyzer' => 'ik_max_word',
'search_analyzer' => 'ik_max_word',
'index_options' => 'offsets',
'store' => true
],
'number' => [
'type' => 'integer',
],
],
];
/**
* 設定 es 檢索返回的欄位
* [@return](https://learnku.com/users/31554) array
*/
public function toSearchableArray() {
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
];
}
}
使用步驟
生成 elatic Template 類似 mysql 表結構
php artisan es:init
更新 elatic 型別對映
php artisan elastic:update-mapping "App\Models\Article"
資料庫資料匯入 elatic
php artisan scout:import "App\Models\Article"
PS: 其他命令
清空 elatic 資料
php artisan scout:flush "App\Models\Article"
使用檢索
$query = Article::search('二胡')
->paginateRaw(3,'article',1);
dd($query->items()['hits']);
其他使用請自行檢視文件
部分參考 部落格:elasticsearch搜尋商品
本作品採用《CC 協議》,轉載必須註明作者和本文連結