elasticsearch-laravel
1. 概念
1. 什么是ES
Elasticsearch 是一個開源的搜索引擎,建立在一個全文搜索引擎庫 Apache Lucene 基礎(chǔ)之上舰蟆。然而楣富,Elasticsearch 不僅僅是 Lucene箍镜,并且也不僅僅只是一個全文搜索引擎。 它可以被下面這樣準(zhǔn)確的形容:
- 一個分布式的實時文檔存儲,每個字段 可以被索引與搜索
- 一個分布式實時分析搜索引擎
- 能勝任上百個服務(wù)節(jié)點的擴(kuò)展和悦,并支持 PB 級別的結(jié)構(gòu)化或者非結(jié)構(gòu)化數(shù)據(jù)
2. 基本概念
1. 索引(Index)
? Elastic 會索引所有字段仁热,經(jīng)過處理后寫入一個反向索引(Inverted Index)榜揖。索引是很多文檔的集合,這些文檔都具備一些相似的特征抗蠢。例如举哟,你可以分別創(chuàng)建客戶,產(chǎn)品目錄和其他數(shù)據(jù)的索引迅矛。索引是通過名字(必須是小寫的)區(qū)分的妨猩,當(dāng)執(zhí)行索引,搜索秽褒,更新和刪除操作時壶硅,這個名字將會被用來引用實際的索引。
2. 類型(Type)
? 你可以在索引中定義一個或多個類型震嫉。類型是索引的一個邏輯分類或劃分森瘪,它的概念完全取決于你自己如何去理解。通常票堵,類型是為一些具備公共字段的文檔定義的扼睬。例如,假想你在運(yùn)行一個博客平臺悴势,并且把其全部的數(shù)據(jù)都存儲索引中窗宇。你可以在索引中定義一個用于保存用戶數(shù)據(jù)的類型,另一個用于保存博客數(shù)據(jù)的類型特纤,還有一個用于保存評論數(shù)據(jù)的類型军俊。在 7.x 以上的版本逐漸去掉類型
3. 文檔(Document)
? 文檔是可以被索引的基本單位。例如捧存,你可以用一個文檔保存單個客戶的數(shù)據(jù)粪躬,另一個文檔保存單個產(chǎn)品的數(shù)據(jù)担败,還有一個文檔保存單個訂單的數(shù)據(jù)。文檔使用一種互聯(lián)網(wǎng)廣泛存在的數(shù)據(jù)交換格式保存-JSON镰官。
你可以在索引/類型中存儲大量你想存儲的數(shù)據(jù)提前。值得注意的是,盡管文檔本質(zhì)上是存放在索引中泳唠,但實際上是被索引到索引中的一個類型中狈网。
4. 節(jié)點(Node)
? 節(jié)點是一個服務(wù)器,也是集群的一部分笨腥,它存儲你的數(shù)據(jù)拓哺,并參與集群的索引和搜索。和集群一樣脖母,節(jié)點也是通過唯一的名字去區(qū)分士鸥,默認(rèn)名字是一個隨機(jī)的UUID,當(dāng)服務(wù)器啟動的時候就會設(shè)置到節(jié)點镶奉。你也可以自定義節(jié)點的名稱础淤。名稱對管理員來說十分重要,它可以幫助你辨認(rèn)出集群中的各個服務(wù)器和哪個節(jié)點相對應(yīng)哨苛。
5. 集群(Cluster)
? 集群是一個或多個節(jié)點(服務(wù)器)的集合,它們聯(lián)合起來保存所有的數(shù)據(jù)(索引以分片為單位分散到多個節(jié)點上保存)并且可以在所有的節(jié)點上進(jìn)行索引和搜索操作币砂。集群通過一個唯一的名字區(qū)分建峭,默認(rèn)的名字是“elasticsearch”。這個名字十分重要决摧,因為一個節(jié)點僅僅可以屬于一個集群亿蒸,并根據(jù)集群名稱加入集群。
2. 安裝
1. windows 安裝啟動
- java環(huán)境安裝
? 由于elasticsearch是基于java運(yùn)行的掌桩,在安裝elasticsearch之前必須安裝java運(yùn)行環(huán)境
? 從Oracle 官網(wǎng)下載并安裝對應(yīng)的java環(huán)境
? 將java添加到環(huán)境變量
- elasticsearch 下載安裝
? 從官網(wǎng)下載elasticsearch最新的版本
? 下載后解壓縮边锁,進(jìn)入bin目錄
? 運(yùn)行elasticsearch.bat文件即可啟動elasticsearch服務(wù)
? 默認(rèn)啟動端口為 9200 , 訪問地址 127.0.0.1:9200 即可看見elasticsearch的啟動信息
- Kibana 下載安裝
? 從官網(wǎng)下載與elasticsearch 對應(yīng)的Kibana版本(必須與elasticsearch版本一致方可啟動)
? 下載后解壓縮,進(jìn)入bin目錄
? 運(yùn)行Kibana.bat文件啟動Kibana服務(wù)
? 默認(rèn)啟動端口為 5600 , 瀏覽器輸入127.0.0.1:5600即可訪問
- IK 中文分詞器安裝
? 從GitHub下載分詞器對應(yīng)版本(與elasticsearch版本保持一致)
? 解壓縮后移動到 elasticsearch 的 plugins 文件夾下并重命名為ik
? 重新啟動elasticsearch服務(wù)即可使用 IK 中文分詞器
2. Linux 安裝啟動
3. 分詞
1. 自定義分詞器
對于逗號分割的標(biāo)簽字段自定義通過逗號分詞的分詞器
PUT /zsj/?pretty
{
"settings": {
"index": {
"number_of_shards": "1",
"number_of_replicas": "1"
},
"analysis": {
"analyzer": {
"comma": {
"type": "pattern",
"pattern":","
}
}
}
}
}
4. laravel開發(fā)過程
1. 下載安裝擴(kuò)展驅(qū)動
安裝laravel/scout
安裝ElasticSearch laravel 驅(qū)動
配置ES驅(qū)動
1. 安裝 laravel/scout
2. 安裝 ElasticSearch 驅(qū)動
3. 配置 ES 驅(qū)動
'driver' => env('SCOUT_DRIVER', 'elasticsearch'),
//增加一個驅(qū)動
'elasticsearch' => [
'index' => env('ELASTICSEARCH_INDEX', 'laravel56_shop'),
'hosts' => [
env('ELASTICSEARCH_HOST', 'http://127.0.0.1:9200'),
],
],
2. 創(chuàng)建模板和索引
創(chuàng)建索引和模板的配置文件
使用laravel命令行生成模板和索引
1. 創(chuàng)建Command命令
php artisan make:command ESInit
會生成一個 Console/Commands
文件夾和 ESInit.php
的文件
2. 編輯文件handle函數(shù)
<?php
namespace App\Console\Commands;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
class ESinit extends Command
{
/**
* 控制臺命令的名稱和簽名波岛。
*
* @var string
*/
protected $signature = 'es:init';
/**
* 控制臺命令的描述
*
* @var string
*/
protected $description = 'init laravel elasticsearch for shopTitle';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
* 向ES中發(fā)送reset風(fēng)格的請求
* @return mixed
*/
public function handle()
{
//創(chuàng)建template
$client = new Client();
$url = config('scout.elasticsearch.hosts')[0] . '/_template/tmp';
$params = [
'json' => [
'template' => config('scout.elasticsearch.index'),
'mappings' => [
'_default_' => [
'dynamic_templates' => [
[
'strings' => [
'match_mapping_type' => 'string',
'mapping' => [
'type' => 'text',
'analyzer' => 'ik_smart',
'fields' => [
'keyword' => [
'type' => 'keyword'
],
],
],
],
]
],
],
],
],
];
//想URL發(fā)送參數(shù)創(chuàng)建template
$client->put($url, $params);
//做記錄 顯示在命令行
$this->info('============ 創(chuàng)建模板成功 ==============');
//創(chuàng)建index
$url = config('scout.elasticsearch.hosts')[0] . '/' . config('scout.elasticsearch.index');
$params = [
'json' => [
'settings' => [
'refresh_interval' => '5s',
'number_of_shards' => 1,
'number_of_replicas' => 0,
],
'mappings' => [
'_default_' => [
'_all' => [
'enabled' => false
],
],
],
],
];
$client->put($url, $params);
$this->info('============ 創(chuàng)建索引成功 ==============');
}
}
3. 掛載命令
編輯 App\Console\Kernel.php 文件
/**
* 將ESInit類加入到 protected $commands數(shù)據(jù)中
*
* @var array
*/
protected $commands = [
ESinit::class
];
使用 php artisan
查看命令是否已生成
使用 php artisan es:init
命令為 ES 生成模板和索引
3. 數(shù)據(jù)寫入和同步更新
1. 創(chuàng)建要同步的數(shù)據(jù)的表模型
創(chuàng)建 product 表模型
<?php
namespace App\Models\Admin;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
/**
* Class Product
* @package App\Models\Admin
*/
class Product extends Model
{
use Searchable;
/**
* 定義索引里的type值,重寫
* @return string
*/
public function searcheableAs()
{
return "product";
}
/**
* 定義那些字段需要搜索
* @return array
*/
public function searchableArray()
{
return [
'title' => $this->title,
'descr' => $this->descr
];
}
}
2. 使用scout導(dǎo)入數(shù)據(jù)
php artisan scout:import "App\Models\Product"
5. 查詢方法
1. 一般查詢
查詢所有數(shù)據(jù)
GET /zsj/_search
{
"size": 2000
}
通過字段匹配查詢
GET /zsj/_search
{
"query": {
"match": {
"author": "joker · 小丑"
}
}
}
多字段聯(lián)合查詢和過濾
GET /zsj/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"subject": {
"query": "林_Linplustar",
"boost": 1.2
}
}
},
{
"match": {
"tags": {
"query": "林_Linplustar",
"boost": 2.0
}
}
},
{
"match_phrase": {
"author": {
"query": "林_Linplustar",
"boost": 40.0
}
}
},
{
"match_phrase": {
"big_class": {
"query": "林_Linplustar",
"boost": 6.0
}
}
},
{
"match_phrase": {
"small_class": {
"query": "林_Linplustar",
"boost": 3.0
}
}
}
],
"must": [
{
"range": {
"displayorder": {
"gte": 0
}
}
},
{
"range": {
"dateline": {
"gte": 1497954476
}
}
},
{
"range": {
"digest": {
"gte": 0
}
}
}
]
}
},
"size": 500
}
2. 其他查詢
查詢某個字段的分詞情況
GET zsj/thread/{id}/_termvectors?fields={field}