政府網(wǎng)站公眾號(hào)建設(shè)方案/谷歌瀏覽器 安卓下載2023版
一、初識(shí) elasticsearch?
1. 了解 ES
① elasticsearch 是一款非常強(qiáng)大的開(kāi)源
? 搜索引擎,可以幫助我們從海量數(shù)據(jù)中
? 快速找到需要的內(nèi)容
②?elasticsearch 結(jié)合 kibana、Logstash、
? Beats,也就是 elastic stack (ELK),被
? 廣泛應(yīng)用在日志數(shù)據(jù)分析、實(shí)時(shí)監(jiān)控等
? 領(lǐng)域
③?elasticsearch 是elastic stack的核心,
? ?負(fù)責(zé)存儲(chǔ)、搜索、分析數(shù)據(jù)
?(2)?Lucene 與 elasticsearch 的區(qū)別
Lucene 是一個(gè)Java語(yǔ)言的搜索引擎類庫(kù)
Lucene的優(yōu)勢(shì):
① 易擴(kuò)展
② 高性能 (基于倒排索引)
?Lucene的缺點(diǎn):
① 只限于 Java 語(yǔ)言開(kāi)發(fā)
② 學(xué)習(xí)曲線陡峭
③ 不支持水平擴(kuò)展
相比于 lucene,elasticsearch 具備下列
優(yōu)勢(shì):
① 支持分布式,可水平擴(kuò)展
② 提供 Restful 接口,可被任何語(yǔ)言
? ? 調(diào)用??
2. 倒排索引
傳統(tǒng)數(shù)據(jù)庫(kù) (如MySQL) 采用正向索引,
局部搜索會(huì)在表上逐條數(shù)據(jù)進(jìn)行掃描,
非常的繁瑣
elasticsearch 采用倒排索引:
會(huì)形成一個(gè)新的表,由兩部分構(gòu)成,進(jìn)
行兩次搜索,先搜詞條再搜文檔
文檔 (document):每條數(shù)據(jù)就是一個(gè)文檔
詞條 (term):文檔按照語(yǔ)義分成的詞語(yǔ)
?
倒排索引中包含兩部分內(nèi)容:
詞條詞典 (Term Dictionary):記錄所有詞條,
以及詞條與倒排列表 (Posting List) 之間的關(guān)
系,會(huì)給詞條創(chuàng)建索引,提高查詢和插入效
率
倒排列表 (Posting List):記錄詞條所在的文
檔 id、詞條出現(xiàn)頻率 、詞條在文檔中的位置
等信息
????????文檔 id:用于快速獲取文檔
????????詞條頻率 (TF):文檔在詞條出現(xiàn)的次數(shù),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?用于評(píng)分?
3. es 的一些概念
(1) es 與 mysql 對(duì)比
(2) 架構(gòu)
Mysql:擅長(zhǎng)事務(wù)類型操作,可以確保
? ? ? ? ? ? ?數(shù)據(jù)的安全和一致性
Elasticsearch:擅長(zhǎng)海量數(shù)據(jù)的搜索、
? ? ? ? ? ? ? ? ? ? ? ? ?分析、計(jì)算
4. 安裝 es、kibana
(1) 部署單點(diǎn) es
(2) 部署?kibana
kibana 可以提供一個(gè) elasticsearch 的可
視化界面
(3) 安裝 IK 分詞器
??1) 分詞器的作用
① 創(chuàng)建倒排索引時(shí)對(duì)文檔分詞
② 用戶搜索時(shí),對(duì)輸入的內(nèi)容分詞
? 2)?默認(rèn)的分詞語(yǔ)法說(shuō)明:
在 kibana 的 DevTools 中測(cè)試:
POST?/_analyze
{"analyzer":?"standard","text":?"床前明月光,疑是地上霜!"
}
① POST:請(qǐng)求方式
② /_analyze:請(qǐng)求路徑,這里省略了,
???????????????????????有 kibana 幫我們補(bǔ)充
③ 請(qǐng)求參數(shù),json風(fēng)格:
????????analyzer:分詞器類型,這里是默
? ? ? ? ? ? ? ? ? ? ? ? ?認(rèn)的 standard 分詞器
????????text:要分詞的內(nèi)容?
默認(rèn)將文字拆除一個(gè)字一個(gè)字的,對(duì)中
文分詞很不友好,所以用 IK 分詞器
? 3) ik 分詞器包含兩種模式:
ik_smart:最少切分,粗粒度
ik_max_word:最細(xì)切分,細(xì)粒度?
一般情況下,為了提高搜索的效果,
需要這兩種分詞器配合使用,既建
索引時(shí)用 ik_max_word 盡可能多的
分詞,而搜索時(shí)用 ik_smart 盡可能
提高匹配準(zhǔn)度,讓用戶的搜索盡可
能的準(zhǔn)確
? ?4) ik 分詞器擴(kuò)展詞條
要拓展ik分詞器的詞庫(kù),只需要修改一
個(gè) ik 分詞器目錄中的 config 目錄中的
IkAnalyzer.cfg.xml 文件:
<?xml?version="1.0"?encoding="UTF-8"?>
<!DOCTYPE?properties?SYSTEM?"http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK?Analyzer?擴(kuò)展配置</comment><!--用戶可以在這里配置自己的擴(kuò)展字典?***?添加擴(kuò)展詞典--><entry?key="ext_dict">ext.dic</entry>
</properties>
然后在名為 ext.dic 的文件中,添加想要
拓展的詞語(yǔ)即可
? 5) 停用詞條
在 stopword.dic 文件中,添加想要拓展的
詞語(yǔ)即可:
<?xml?version="1.0"?encoding="UTF-8"?>
<!DOCTYPE?properties?SYSTEM?"http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK?Analyzer?擴(kuò)展配置</comment><!--用戶可以在這里配置自己的擴(kuò)展字典--><entry?key="ext_dict">ext.dic</entry><!--用戶可以在這里配置自己的擴(kuò)展停止詞字典??***?添加停用詞詞典--><entry?key="ext_stopwords">stopword.dic</entry>
</properties>
(4) 部署 es 集群
直接使用 docker-compose 來(lái)完成
二、索引庫(kù)操作
1. mapping 映射屬性
(1) mapping 是對(duì)索引庫(kù)中文檔的約束,常
? ? 見(jiàn)的 mapping 屬性包括:
① type:字段數(shù)據(jù)類型,常見(jiàn)的簡(jiǎn)單類型有:
字符串:text (可分詞的文本)、keyword
? ?(精確值,例如:品牌、國(guó)家、ip 地址)
數(shù)值:long、integer、short、byte、
? ? ? ? ? ?double、float
布爾:boolean
日期:date
對(duì)象:object
② index:是否創(chuàng)建索引,默認(rèn)為 true
③ analyzer:使用哪種分詞器
④ properties:該字段的子字段
2. 索引庫(kù)的 CRUD
(1) 創(chuàng)建索引庫(kù)
ES 中通過(guò) Restful 請(qǐng)求操作索引庫(kù)、
文檔,請(qǐng)求內(nèi)容用 DSL 語(yǔ)句來(lái)表示
創(chuàng)建索引庫(kù)和 mapping 的 DSL 語(yǔ)法如下:
PUT /索引庫(kù)名稱
PUT /索引庫(kù)名稱
{"mappings": {"properties": {"字段名":{"type": "text","analyzer": "ik_smart"},"字段名2":{"type": "keyword","index": "false"},"字段名3":{"properties": {"子字段": {"type": "keyword"}}},// ...略}}
}
(2) 查看索引庫(kù)
GET /索引庫(kù)名
(3) 修改索引庫(kù)
索引庫(kù)和 mapping 一旦創(chuàng)建無(wú)法修改,
但是可以添加新的字段,語(yǔ)法如下:
PUT /索引庫(kù)名/_mapping
PUT /索引庫(kù)名/_mapping
{"properties": {"新字段名":{"type": "integer"}}
}
(4) 刪除索引庫(kù)
DELETE /索引庫(kù)名
三、文檔操作
1. 新增文檔
POST /索引庫(kù)名/_doc/文檔id
POST /索引庫(kù)名/_doc/文檔id
{"字段1": "值1","字段2": "值2","字段3": {"子屬性1": "值3","子屬性2": "值4"},// ...
}
2. 查詢文檔
GET /索引庫(kù)名/_doc/文檔id
3. 刪除文檔
DELETE /索引庫(kù)名/_doc/文檔id
4. 修改文檔
(1) 全量修改
刪除舊文檔,添加新文檔
本質(zhì)是:根據(jù)指定的 id 刪除文檔,新增
? ? ? ? ? ? ? 一個(gè)相同 id 的文檔
PUT /{索引庫(kù)名}/_doc/文檔id
{"字段1": "值1","字段2": "值2",// ... 略
}
(2)?增量修改
修改指定字段值
POST /{索引庫(kù)名}/_update/文檔id
{"doc": {"字段名": "新的值",}
}
5.?Dynamic Mapping
我們向 ES 中插入文檔時(shí),如果文檔中
字段沒(méi)有對(duì)應(yīng)的 mapping,ES 會(huì)幫助
我們字段設(shè)置 mapping
JSON類型 | Elasticsearch類型 |
---|---|
字符串 | ① 日期格式字符串:mapping 為 date 類型 ② 普通字符串:mapping 為 text 類型,并添加 ? ? ?keyword 類型子字段 |
布爾值 | boolean |
浮點(diǎn)數(shù) | float |
整數(shù) | long |
對(duì)象嵌套 | object,并添加 properties |
數(shù)組 | 由數(shù)組中的第一個(gè)非空類型決定 |
空值 | 忽略 |
四、RestClient 操作索引庫(kù)
RESTClient 是一款用于測(cè)試各種 Web
服務(wù)的插件,它可以向服務(wù)器發(fā)送各種
HTTP請(qǐng)求(用戶也可以自定義請(qǐng)求方式),
并顯示服務(wù)器響應(yīng)
本質(zhì)就是組裝 DSL 語(yǔ)句,通過(guò) http請(qǐng)求
發(fā)送給 ES
1. 創(chuàng)建索引庫(kù)
(1) 導(dǎo)入數(shù)據(jù)庫(kù)
(2) 分析數(shù)據(jù)結(jié)構(gòu)
mapping 要考慮的問(wèn)題:
字段名、數(shù)據(jù)類型、是否參與搜索、是
否分詞,如果分詞,分詞器是什么
(3)?初始化 JavaRestClient
① 引入依賴
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency><properties><java.version>1.8</java.version><elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
② 初始化
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")
));
(4) 創(chuàng)建索引庫(kù)代碼
@Testvoid testCreateHotelIndex() throws IOException {// 1.創(chuàng)建Request對(duì)象CreateIndexRequest request = new CreateIndexRequest("hotel");// 2.請(qǐng)求參數(shù),MAPPING_TEMPLATE是靜態(tài)常量字符串,內(nèi)容是創(chuàng)建索引庫(kù)的DSL語(yǔ)句 request.source(MAPPING_TEMPLATE, XContentType.JSON);// 3.發(fā)起請(qǐng)求, indices 返回的對(duì)象中包含索引庫(kù)操作的所有方法client.indices().create(request, RequestOptions.DEFAULT);
}
2. 刪除索引庫(kù)代碼
@Test
void testDeleteHotelIndex() throws IOException {// 1.創(chuàng)建Request對(duì)象DeleteIndexRequest request = new DeleteIndexRequest("hotel");// 2.發(fā)起請(qǐng)求client.indices().delete(request, RequestOptions.DEFAULT);
}
3. 判斷索引庫(kù)是否存在
@Test
void testExistsHotelIndex() throws IOException {// 1.創(chuàng)建Request對(duì)象GetIndexRequest request = new GetIndexRequest("hotel");// 2.發(fā)起請(qǐng)求 boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);// 3.輸出System.out.println(exists);
}
五、RestClient 操作文檔
1. 初始化
public class ElasticsearchDocumentTest { // 客戶端private RestHighLevelClient client;@BeforeEachvoid setUp() {client = new RestHighLevelClient(RestClient.builder( HttpHost.create("http://192.168.150.101:9200")));}@AfterEachvoid tearDown() throws IOException {client.close();}
}
2. 新增文檔
@Test
void testIndexDocument() throws IOException {// 1.創(chuàng)建request對(duì)象IndexRequest request = new IndexRequest("indexName").id("1");// 2.準(zhǔn)備JSON文檔request.source("{\"name\": \"Jack\", \"age\": 21}", XContentType.JSON);// 3.發(fā)送請(qǐng)求client.index(request, RequestOptions.DEFAULT);
}
3. 查詢文檔
@Test
void testGetDocumentById() throws IOException {// 1.創(chuàng)建request對(duì)象GetRequest request = new GetRequest("indexName", "1");// 2.發(fā)送請(qǐng)求,得到結(jié)果GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.解析結(jié)果String json = response.getSourceAsString();System.out.println(json);
}
4. 修改文檔
@Test
void testUpdateDocumentById() throws IOException {// 1.創(chuàng)建request對(duì)象UpdateRequest request = new UpdateRequest("indexName", "1");// 2.準(zhǔn)備參數(shù),每2個(gè)參數(shù)為一對(duì) key valuerequest.doc("age", 18,"name", "Rose");// 3.更新文檔client.update(request, RequestOptions.DEFAULT);
}
5. 刪除文檔
@Test
void testDeleteDocumentById() throws IOException {// 1.創(chuàng)建request對(duì)象DeleteRequest request = new DeleteRequest("indexName", "1");// 2.刪除文檔 client.delete(request, RequestOptions.DEFAULT);
}
6. 批量導(dǎo)入文檔
@Test
void testBulk() throws IOException {// 1.創(chuàng)建Bulk請(qǐng)求BulkRequest request = new BulkRequest();// 2.添加要批量提交的請(qǐng)求:這里添加了兩個(gè)新增文檔的請(qǐng)求request.add(new IndexRequest("hotel").id("101").source("json source", XContentType.JSON));request.add(new IndexRequest("hotel").id("102").source("json source2", XContentType.JSON));// 3.發(fā)起bulk請(qǐng)求client.bulk(request, RequestOptions.DEFAULT);
}