docker安裝elasticsearch
關(guān)于es的詳細(xì)介紹以及安裝包編譯安裝的方式搁进,可以看之前的文章:安裝Elasticsearch搜索引擎
這次換個花樣嗓违,使用docker(這里不解釋docker是什么了,不了解的自行百度)來安裝李破,直接開搞,操作如下
-
安裝docker
# 安裝 yum install -y docker # 查看版本信息 docker version # 修改docker的鏡像源 vim /etc/docker/daemon.json { "registry-mirrors": ["https://ftnejmh3.mirror.aliyuncs.com"] } # 啟動docker systemctl start docker # 停止docker systemctl stop docker # 查看docker狀態(tài) systemctl status docker # 重新啟動docker systemctl restart docker
如果docker沒有命令自動補(bǔ)全功能,可以安裝如下
yum -y install bash-completion source /usr/share/bash-completion/bash_completion
-
拉取es鏡像(文件有點大恐仑,需要一定時間)
docker pull elasticsearch:7.12.1
-
在宿主機(jī)創(chuàng)建和容器內(nèi)共享的目錄
# 存放配置文件目錄 mkdir -p /docker/es/conf # 存放數(shù)據(jù)目錄 mkdir -p /docker/es/data # 存放日志目錄 mkdir -p /docker/es/logs # 存放插件目錄 mkdir -p /docker/es/plugins # 創(chuàng)建好目錄后為了防止下邊創(chuàng)建容器報錯,給宿主機(jī)的這個es目錄賦個讀寫權(quán)限 chmod -R 777 /docker/es/
-
創(chuàng)建es配置文件(參數(shù)意思不解釋为鳄,上方提到的文章內(nèi)有解釋)
vi /docker/es/conf/elasticsearch.yml
cluster.name: my-application node.name: node-1 path.data: /usr/share/elasticsearch/data path.logs: /usr/share/elasticsearch/logs network.host: 0.0.0.0 http.port: 9200 cluster.initial_master_nodes: ["node-1"]
-
構(gòu)建容器(構(gòu)建很快裳仆,但是容器內(nèi)es的啟動速度很慢,構(gòu)建完先耐心等待一下)
docker run -p 9200:9200 -d --name es -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -v /docker/es/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /docker/es/data:/usr/share/elasticsearch/data -v /docker/es/plugins:/usr/share/elasticsearch/plugins -v /docker/es/logs:/usr/share/elasticsearch/logs --privileged=true elasticsearch:7.12.1
-
異常處理
好事多磨孤钦,一般這里都會出點小問題歧斟,啟動失敗使用
docker logs es | grep error
命令來查看報錯信息纯丸。我遇到的有異常:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
解決方案:
1. 修改配置sysctl.conf: vi /etc/sysctl.conf 2. 在尾行添加以下內(nèi)容: vm.max_map_count=655300 3. 刷新配置: sysctl -p
-
測試,在瀏覽器中訪問服務(wù)地址+9200的端口静袖,可以顯示以下信息證明安裝成功
PS:如果打不開觉鼻,請檢查es是否正確啟動以及9200端口是否開放
{ "name" : "node-1", "cluster_name" : "my-application", "cluster_uuid" : "b-ovHR-GRvunpTmWOfoLKw", "version" : { "number" : "7.12.1", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "3186837139b9c6b6d23c3200870651f10d3343b7", "build_date" : "2021-04-20T20:56:39.040728659Z", "build_snapshot" : false, "lucene_version" : "8.8.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
安裝es的可視化面板 kibana
-
拉取鏡像
docker pull kibana:7.12.1
-
在宿主機(jī)創(chuàng)建和容器內(nèi)共享的目錄
mkdir -p /docker/kibana/conf
-
創(chuàng)建配置文件
vi /docker/kibana/conf/kibana.ymlserver.name: kibana server.host: "0.0.0.0" elasticsearch.hosts: ["http://你的es地址:9200"] xpack.monitoring.ui.container.elasticsearch.enabled: true
-
構(gòu)建容器
docker run -p 5601:5601 -d --name kibana -v /docker/kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml --privileged=true kibana:7.12.1
訪問測試:http://服務(wù)ip:5601
安裝es的ik分詞器
-
下載安裝包
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.12.1
-
解壓安裝包
PS:這個安裝包解壓完文件是分散的,所以需要在 plugins 目錄下先建好放置文件的目錄
mkdir /docker/es/plugins/ik mv elasticsearch-analysis-ik-7.12.1.zip /docker/es/plugins/ik/ cd /docker/es/plugins/ik unzip elasticsearch-analysis-ik-7.12.1.zip rm -rf elasticsearch-analysis-ik-7.12.1.zip
-
重啟es容器
docker restart es
-
注意事項
安裝es的ik分詞器可能會導(dǎo)致es內(nèi)存溢出队橙,可以在es配置中增加內(nèi)存限制
indices.fielddata.cache.size: 50%
es在laravel中的應(yīng)用
-
安裝composer組件包
composer require elasticsearch/elasticsearch "7.12.x" --ignore-platform-reqs
-
配置
# 在 .env 文件中加入es的地址配置坠陈,如果是集群存在多個地址則用 ,隔開 ES_HOSTS=172.17.0.8,172.17.0.9,172.17.0.10 # 在 config/database.php 配置文件中加入 # 端口不用加捐康,默認(rèn)就是9200仇矾,但是如果改了端口那這里就要加入端口的配置 'elasticsearch' => [ 'hosts' => explode(',', env('ES_HOSTS')), ]
-
初始化 Elasticsearch 對象,并注入到 laravel 容器中
在 App/Providers/AppServiceProvider.php 文件的register方法中定義服務(wù)對象
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Elasticsearch\ClientBuilder as ESClientBuilder; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // 注冊一個名為 es 的單例 $this->app->singleton('es', function () { // 從配置文件讀取 Elasticsearch 服務(wù)器列表 $builder = ESClientBuilder::create()->setHosts(config('database.elasticsearch.hosts')); // 如果是開發(fā)環(huán)境 if (app()->environment() === 'local'){ // 配置日志吹由,Elasticsearch 的請求和返回數(shù)據(jù)將打印到日志文件中若未,便于調(diào)試 $builder->setLogger(app('log')->driver()); } return $builder->build(); }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } }
然后就可以在項目中使用 app('es') 的方式來調(diào)用es了
-
測試是否配置成功
[root@localhost blog]# php artisan tinker Psy Shell v0.10.8 (PHP 7.4.20 — cli) by Justin Hileman >>> app('es')->info() => [ "name" => "node-1", "cluster_name" => "my-application", "cluster_uuid" => "b-ovHR-GRvunpTmWOfoLKw", "version" => [ "number" => "7.12.1", "build_flavor" => "default", "build_type" => "docker", "build_hash" => "3186837139b9c6b6d23c3200870651f10d3343b7", "build_date" => "2021-04-20T20:56:39.040728659Z", "build_snapshot" => false, "lucene_version" => "8.8.0", "minimum_wire_compatibility_version" => "6.8.0", "minimum_index_compatibility_version" => "6.0.0-beta1", ], "tagline" => "You Know, for Search", ] >>>
使用
app('es')->info()
可以打印出es相關(guān)信息,則安裝配置成功 -
在laravel中簡單封裝一個類來使用es
這里只以搜索為例倾鲫,增刪改都很簡單粗合,就不演示了
創(chuàng)建一個 service 類,來處理es搜索的結(jié)構(gòu)體
<?php /** * Created by PhpStorm * User: Ricky Wong * Date: 2021/8/1 * Time: 19:58 */ namespace App\Services; class ElasticSearchService { /** * 定義基礎(chǔ)結(jié)構(gòu)體 * @var array */ protected $params = [ 'index' => 'products', 'type' => '_doc', 'body' => [ 'query' => [ 'bool' => [ 'filter' => [], 'must' => [] ] ] ] ]; /** * 分頁 * @param int $size 每頁顯示多少條 * @param int $page 頁碼 * @return $this */ public function paginate($size = 20, $page = 1) { $this->params['body']['from'] = ($page - 1) * $size; $this->params['body']['size'] = $size; return $this; } /** * 數(shù)據(jù)狀態(tài)值精確查詢 * @param int $status 狀態(tài)標(biāo)識 * @return $this */ public function status($status = 1) { $this->params['body']['query']['bool']['filter'] = [ 'term' => ['status' => $status] ]; return $this; } /** * 排序 * 如需多字段排序多次調(diào)用此方法即可 * @param string $field 排序字段 * @param string $direction 排序方式 asc|desc * @return $this */ public function order($field, $direction) { if (!isset($this->params['body']['sort'])) { $this->params['body']['sort'] = []; } $this->params['body']['sort'][] = [$field => $direction]; return $this; } /** * 關(guān)鍵詞乌昔,按多字段權(quán)重搜索 * @param array $keywords 搜索詞數(shù)組 * @return $this */ public function keywords($keywords) { $keywords = is_array($keywords) ? $keywords : [$keywords]; foreach ($keywords as $keyword) { $this->params['body']['query']['bool']['must'][] = [ 'multi_match' => [ 'query' => $keyword, 'fields' => [ 'long_name^3', 'name^2' ], // most_fields 多字段匹配度更高 best_fields 完全匹配占比更高 'type' => 'most_fields' ] ]; } return $this; } /** * 指定需要返回的字段 * @param array $fields 字段數(shù)組 * @return $this */ public function select($fields = []) { $this->params['body']['_source'] = $fields; return $this; } /** * 搜索詞高亮設(shè)置 * @param array $fields 高亮搜索詞數(shù)組 * @return $this */ public function highlight($fields) { $array = []; foreach ($fields as $field) { $array[$field] = (object)[]; } $this->params['body']['highlight'] = [ // 自定義高亮樣式 'pre_tags' => "<p style='color: red;'>", 'post_tags' => "</p>", 'fields' => $array ]; return $this; } /** * 返回結(jié)構(gòu)體 * @return array */ public function getParams() { return $this->params; } }
創(chuàng)建控制器隙疚,在其中定義方法來調(diào)用service,這里只展示這個方法
/** * 搜索 * @param Request $request * @param ElasticSearchService $service * @return \Illuminate\Http\JsonResponse */ public function search(Request $request, ElasticSearchService $service) { $page = $request->input('page', 1); $size = $request->input('perPage', 20); $keyword = $request->input('keyword', ''); $order = $request->input('order', ''); try { $builder = $service->status()->paginate($size, $page); if (!empty($keyword)) { // 將多個以空格隔開的關(guān)鍵詞轉(zhuǎn)為數(shù)組 $keywords = array_filter(explode(' ', $keyword)); $builder->keywords($keywords); } if (!empty($order)) { if (preg_match('/^(.+)_(asc|desc)$/', $order,$match)) { $builder->order($match[1], $match[2]); } } $params = $builder->select(['name', 'long_name'])->highlight(['name', 'long_name'])->getParams(); return response()->json(['result' => true, 'data' => app('es')->search($params)]); } catch (\Exception $e) { Log::error($e->getMessage()); return response()->json(['result' => false, 'data' => []]); } }