Elasticsearch的安裝和使用——Docker
Elasticsearch官方使用參考手冊(cè):https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
ELK簡(jiǎn)介
E表示Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎.為所有類型的數(shù)據(jù)提供近乎實(shí)時(shí)的搜索和分析。無(wú)論您擁有結(jié)構(gòu)化或非結(jié)構(gòu)化文本、數(shù)字?jǐn)?shù)據(jù)還是地理空間數(shù)據(jù),Elasticsearch 都能以支持快速搜索的方式高效地存儲(chǔ)和索引它。
L表示Logstash是一款數(shù)據(jù)轉(zhuǎn)換工具Logstash。由于Elasticsearch只接收J(rèn)SON格式的數(shù)據(jù),像數(shù)據(jù)庫(kù)、系統(tǒng)日志、網(wǎng)頁(yè)數(shù)據(jù)這些亂七八糟的數(shù)據(jù)就無(wú)法放入Elasticsearch,就誕生了一款數(shù)據(jù)轉(zhuǎn)換工具Logstash。Logstash致力于將不同來(lái)源的數(shù)據(jù)進(jìn)行集中、轉(zhuǎn)換和過(guò)濾,轉(zhuǎn)換成Elasticsearch需要的數(shù)據(jù)。
K表示Kibana是一款可視化操作工具。為Elasticsearch提供可視化操作界面,使您能夠以交互方式探索、可視化和分享對(duì)數(shù)據(jù)的見(jiàn)解,并管理和監(jiān)控堆棧。
Docker安裝Elasticsearch
第一步:開(kāi)啟Docker
systemctl start docker
第二步:拉取Elasticsearch的鏡像
docker pull Elasticsearch:7.17.3
第三步:拉取Kibana鏡像
docker pull kibana:7.17.3
第四步:?jiǎn)?dòng)Elasticsearch和Kinaba(啟動(dòng)方式一)
docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name=es elasticsearch:7.17.3
docker run -d -p 5601:5601 -e ELASTICSEARCH_HOSTS="http://192.168.213.142:9200" --name=kibana kibana:7.17.3
第五步、編寫docker-compose啟動(dòng)(啟動(dòng)方式二)
# 注意version要和docker-compose的版本對(duì)應(yīng)
version: '3.8'
services:
elasticsearch:
image: elasticsearch:7.17.3
ports:
- 9200:9200
- 9300:9300
environment:
- 'discovery.type=single-node'
container_name: elasticsearch
kinaba:
image: kibana:7.17.3
ports:
- 5601:5601
environment:
- ELASTICSEARCH_HOSTS=["http://elasticsearch:9200"]
container_name: kibana
第六步:?jiǎn)?dòng)docker-compose
docker-compose up
基本概念
Elasticsearch | 數(shù)據(jù)庫(kù) | 備注 |
---|---|---|
Index | Database | 一個(gè)index就相當(dāng)于是一個(gè)數(shù)據(jù)庫(kù),表示所有文檔的集合 |
Type | Table | 一個(gè)type就相當(dāng)于是數(shù)據(jù)庫(kù)中的一個(gè)表,type(在7.0之后type為固定值_doc) |
Document | Row | 一個(gè)document就相當(dāng)于是數(shù)據(jù)庫(kù)表中的一個(gè)行 |
Field | Column | 一個(gè)Field就相當(dāng)于是數(shù)據(jù)庫(kù)表中的一個(gè)列 |
Mapping | Schema(大綱) | 一個(gè)Mapping就相當(dāng)于是數(shù)據(jù)庫(kù)表中的一個(gè)約束(表結(jié)構(gòu)),包含了該索引所有的屬性和屬性對(duì)應(yīng)的數(shù)據(jù)類型 |
相關(guān)命令
查看所有的索引
# 查看所有的索引
GET _cat/indices
查看對(duì)應(yīng)索引的所有的數(shù)據(jù)
# 查看對(duì)應(yīng)索引的所有的數(shù)據(jù)
# 語(yǔ)法:GET 索引/_search
GET kibana_sample_data_flights/_search
響應(yīng)中最重要的部分是hits,它包含了total字段來(lái)表示匹配到的文檔總數(shù),hits數(shù)組還包含了匹配到的前10條數(shù)據(jù)。hits數(shù)組中的每個(gè)結(jié)果都包含_index、_type和文檔的_id字段,被加入到_source字段中這意味著在搜索結(jié)果中我們將可以直接使用全部文檔。這不像其他搜索引擎只返回文檔ID,需要你單獨(dú)去獲取文檔。
每個(gè)節(jié)點(diǎn)都有一個(gè)_score字段,這是相關(guān)性得分(relevance score),它衡量了文檔與查詢的匹配程度。默認(rèn)的,返回的結(jié)果中關(guān)聯(lián)性最大的文檔排在首位;這意味著,它是按照_score降序排列的。這種情況下,我們沒(méi)有指定任何查詢,所以所有文檔的相關(guān)性是一樣的,因此所有結(jié)果的_score都是取得一個(gè)中間值1max_score指的是所有文檔匹配查詢中_score的最大值。在查詢時(shí),必須加上track_total_hits,不然就只顯示10000
# 查看對(duì)應(yīng)索引的所有的數(shù)據(jù)
# 語(yǔ)法:GET 索引/_search
GET kibana_sample_data_flights/_search
{
"track_total_hits":true
}
查看對(duì)應(yīng)索引的數(shù)據(jù)總量
# 查看對(duì)應(yīng)索引的數(shù)據(jù)總量
GET kibana_sample_data_flights/_count
# 按條件查詢數(shù)據(jù)總量
GET user/_count
{
"query": {
"match": {
"about": "陸軍上將"
}
}
}
查看某一個(gè)Document(某一條數(shù)據(jù))的詳細(xì)數(shù)據(jù)
# 查看某一個(gè)Document(某一條數(shù)據(jù))的詳細(xì)數(shù)據(jù)
# 語(yǔ)法:GET Document所在的索引/_doc/Document對(duì)應(yīng)的id
GET kibana_sample_data_flights/_doc/mpxoJ4oB0aXjbqrzJSyK
查看對(duì)應(yīng)索引的全部mapping(屬性)
# 查看對(duì)應(yīng)索引的全部mapping(屬性)
# 語(yǔ)法:GET 索引/_mapping
GET kibana_sample_data_flights/_mapping
# 或者
GET kibana_sample_data_flights
命令 | 說(shuō)明 |
---|---|
_doc | 可以對(duì)具體的數(shù)據(jù)進(jìn)行查詢、修改、添加、刪除的操作,如果向索引中添加一條id已經(jīng)存在的數(shù)據(jù)會(huì)將原來(lái)數(shù)據(jù)覆蓋,否則直接添加 |
_create | 可以對(duì)具體的數(shù)據(jù)進(jìn)行添加,如果向索引中添加一條id已經(jīng)存在的數(shù)據(jù)會(huì)報(bào)錯(cuò)添加不成功,否則直接添加 |
_update | 可以對(duì)具體的數(shù)據(jù)進(jìn)行修改,如果數(shù)據(jù)的屬性已經(jīng)存在則修改,否則直接給數(shù)據(jù)添加一個(gè)屬性(數(shù)據(jù)添加或者修改屬性:要么直接用_doc覆蓋,要么直接用_update添加) |
_search | 對(duì)整個(gè)索引進(jìn)行搜索 |
_mapping | 對(duì)整個(gè)索引進(jìn)行獲取屬性 |
CRUD增刪改查
# 添加數(shù)據(jù),如果索引存在直接向索引添加數(shù)據(jù),如果索引不存在則會(huì)創(chuàng)建索引,并向索引中添加數(shù)據(jù)
# 語(yǔ)法:POST 索引/_doc/id
POST user/_doc/1
{
"firstname":"Douglas",
"lastname":"MacArthur"
}
# 添加數(shù)據(jù),如果索引存在直接向索引添加數(shù)據(jù),如果索引中存在一條相同id的數(shù)據(jù)則會(huì)報(bào)錯(cuò),如果索引不存在則會(huì)創(chuàng)建索引,并向索引中添加數(shù)據(jù)
# 語(yǔ)法:POST 索引/_create/id
POST user/_create/2
{
"firstname":"Douglas",
"lastname":"Jack",
"age":47
}
# 修改數(shù)據(jù),必須是在索引和數(shù)據(jù)都存在的情況下,如果數(shù)據(jù)的屬性已經(jīng)存在則修改,否則直接給數(shù)據(jù)添加一個(gè)屬性
# 數(shù)據(jù)添加或者修改屬性:要么直接用_doc覆蓋,要么直接用_update添加
# 語(yǔ)法:POST 索引/_create/id
POST user/_update/2
{
"doc":{
"age":53,
"address":"American"
}
}
# 刪除索引中的某條數(shù)據(jù),不管數(shù)據(jù)存不存在都會(huì)刪除
# 語(yǔ)法:POST 索引/_doc/id
DELETE user/_doc/90
#刪除索引
DELETE user
# 獲取索引中的某一條數(shù)據(jù)
GET user/_doc/2
批量添加
# 批量添加
# _bulk的操作,行為和請(qǐng)求體數(shù)據(jù) 都是不能換行的。
POST user/_bulk
{"index":{"_id":1}}
{"firstname" : "Douglas","lastname" : "MacArthur","chineseName" : "道格拉斯·麥克阿瑟","age":48,"address":"American","graduationSchool" : {"englishName" : "The United States Military Academy(West Point)","chinese" : "美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about" : "1899年,麥克阿瑟考入西點(diǎn)軍校。第一次世界大戰(zhàn)期間晉升為上校并前往法國(guó)參戰(zhàn)。1919年6月,被任命為西點(diǎn)軍校校長(zhǎng)。20世紀(jì)20-30年代擔(dān)任陸軍參謀長(zhǎng)。第二次世界大戰(zhàn)時(shí)期歷任美國(guó)遠(yuǎn)東軍司令,西南太平洋戰(zhàn)區(qū)盟軍司令。1944年麥克阿瑟被授予陸軍五星上將軍銜。1945年9月2日以盟軍最高統(tǒng)帥的身份主持了對(duì)日本的受降儀式并代表同盟國(guó)簽字。二戰(zhàn)后出任駐日盟軍最高司令長(zhǎng)官、遠(yuǎn)東軍司令等職,對(duì)日本實(shí)行了一系列改革,之后出任“聯(lián)合國(guó)軍”總司令。1952年,參與美國(guó)共和黨總統(tǒng)初選,但未勝出。1964年4月5日,麥克阿瑟因膽結(jié)石去世,終年84歲。","services":"陸軍"}
{"index":{"_id":2}}
{"firstname" : "William Daniel","lastname" : "Leahy","chineseName":"威廉·丹尼爾·萊希","age" : 32,"address" : "American", "graduationSchool" : {"englishName" : "The United States Annapolis Naval Academy","chinese" : "美國(guó)亞那波里斯海軍學(xué)院"},"about" : "威廉·丹尼爾·萊希1897年畢業(yè)於美國(guó)亞那波里斯海軍學(xué)院,第一次世界大戰(zhàn)期間指揮一艘海軍運(yùn)輸艦,同當(dāng)時(shí)任海軍部助理部長(zhǎng)的富蘭克林·羅斯福結(jié)成生死之交。歷任軍械局局長(zhǎng)(1927~1931)、航行局局長(zhǎng)(1933~1935)、美國(guó)海軍作戰(zhàn)部長(zhǎng)(1937年-1939年)、1936年晉升為海軍上將。1939年因年邁退休。數(shù)月后,被羅斯??偨y(tǒng)任命為波多黎各總督(1939年-1940年)、接著出任駐維希法國(guó)大使(1941年-1942年),美國(guó)參戰(zhàn)后,擔(dān)任新設(shè)置的總統(tǒng)參謀長(zhǎng)職務(wù)(1942年-1949年)并主持美國(guó)參謀長(zhǎng)聯(lián)席會(huì)議,和英帝國(guó)總參謀長(zhǎng)阿蘭布魯克子爵一起決定盟國(guó)大戰(zhàn)略。1944年成為美國(guó)歷史上首位獲五星上將軍銜的軍官。次年隨羅斯福參加雅爾塔會(huì)議。1945年4月羅斯福去世后,他在杜魯門總統(tǒng)任內(nèi)繼任原職。1949年退休,寫有戰(zhàn)爭(zhēng)回憶錄《身歷其境》(I Was There,1950)。","services":"海軍"}
{"index":{"_id":3}}
{"firstname" : "Dwight David","lastname" : "Eisenhower","chineseName" : "德懷特·戴維·艾森豪威爾","age" : 53,"address" : "American","graduationSchool" : {"englishName" : "The United States Military Academy(West Point)","chinese" : "美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about" : "艾森豪威爾在1915年畢業(yè)于西點(diǎn)軍校。1944年任歐洲盟軍最高司令,晉升為五星上將。1952年競(jìng)選總統(tǒng)獲勝,成為第34任美國(guó)總統(tǒng),1956年再次競(jìng)選獲勝,蟬聯(lián)總統(tǒng)。1950年前后任美國(guó)哥倫比亞大學(xué)校長(zhǎng)。1969年3月28日,艾森豪威爾在華盛頓因心臟病去世,享年78歲。","services":"陸軍"}
{"index":{"_id":4}}
{"firstname" : "James Alward","lastname" : "Van Fleet","chineseName":"詹姆斯·奧爾沃德·范佛里特","age" : 47,"address" : "American","graduationSchool":{"englishName":"The United States Military Academy(West Point)","chinese":"美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about":"1915年美國(guó)西點(diǎn)軍校畢業(yè),晉升中尉。1916年參加墨西哥邊界之戰(zhàn)。1918年參加第一次世界大戰(zhàn)。第二次世界大戰(zhàn)期間任第4師第8步兵團(tuán)團(tuán)長(zhǎng)、第23軍第90師師長(zhǎng)、第三軍軍長(zhǎng)。1947年任第一集團(tuán)軍副司令。同年任美駐歐洲司令部副總司令。1948年在希臘任聯(lián)合軍事先頭增援集團(tuán)軍司令。1951年在朝鮮戰(zhàn)爭(zhēng)中任美國(guó)第八集團(tuán)軍司令。1953年以上將軍銜退休","services":"陸軍"}
{"index":{"_id":5}}
{"firstname" : "Mark Wayne","lastname" : "Clark","chineseName":"馬克·韋恩·克拉克","age" : 49,"address" : "American","graduationSchool":{"englishName":"The United States Military Academy(West Point)","chinese":"美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about":"美國(guó)四星上將,第二次世界大戰(zhàn)期間的美國(guó)第五集團(tuán)軍司令與朝鮮戰(zhàn)爭(zhēng)時(shí)的聯(lián)合國(guó)軍指揮官。","services":"陸軍"}
{"index":{"_id":6}}
{"firstname" : "Matthew Bunker","lastname" : "Ridgway","chineseName":"馬修·邦克·李奇微","age" : 47,"address" : "American","graduationSchool":{"englishName":"The United States Military Academy(West Point)","chinese":"美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about":"美國(guó)著名軍事家、陸軍上將。1895年,李奇微出生于美國(guó)弗吉尼亞州門羅堡,曾經(jīng)參加過(guò)朝鮮戰(zhàn)爭(zhēng)。1993年7月26日,李奇微去世。","services":"陸軍"}
高級(jí)條件查詢
某一個(gè)字段中包含了其中的一個(gè)關(guān)鍵詞的查詢
# 查詢姓名包含懷或者特的人
# 某一個(gè)字段中包含了多個(gè)關(guān)鍵詞中的一個(gè)關(guān)鍵詞的查詢
GET user/_search
{
"query": {
"match": {
"chineseName": "懷 特"
}
}
}
某一個(gè)字段的包含了所有關(guān)鍵詞的查詢
# 查詢姓名包含懷和特的人
# 某一個(gè)字段的包含了所有關(guān)鍵詞的查詢
GET user/_search
{
"query": {
"match": {
"chineseName": {
"query": "懷 特",
"operator": "and"
}
}
}
}
將關(guān)鍵詞作為一個(gè)短語(yǔ)查詢
# 查詢姓名包含懷和者特的人
# 將關(guān)鍵詞作為一個(gè)短語(yǔ)查詢
GET user/_search
{
"query": {
"match_phrase": {
"chineseName": "懷 特"
}
}
}
某一個(gè)字段的范圍查詢
# 查詢年齡在47到50歲之間的人
# 某一個(gè)字段的范圍查詢
GET user/_search
{
"query": {
"range": {
"age": {
"gte": 47,
"lte": 50
}
}
}
}
兩個(gè)字段中有一個(gè)包含了關(guān)鍵詞的查詢
# 查詢畢業(yè)院?;蛘遖bout中包含了"美國(guó)"的人
# 兩個(gè)字段中有一個(gè)包含了關(guān)鍵詞的查詢
GET user/_search
{
"query": {
"multi_match": {
"query": "美國(guó)",
"fields": ["graduationSchool.chinese","about"]
}
}
}
多條件查詢,必須滿足所有的查詢條件
# 查詢年齡在49歲到53歲之間并且about中包含了總統(tǒng)的人
# 多條件查詢,必須滿足所有的查詢條件
GET user/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 49,
"lte": 53
}
}
},
{
"match": {
"about": "總統(tǒng)"
}
}
]
}
}
}
高級(jí)復(fù)合查詢——should中的條件是或者關(guān)系,must中的條件是并且關(guān)系
# 高級(jí)復(fù)合查詢
# should中的條件是或者關(guān)系,must中的條件是并且關(guān)系
GET user/_search
{
"query": {
"bool": {
"should": [
{
"range": {
"age": {
"gte": 49,
"lte": 53
}
}
}
],
"must": [
{
"match": {
"chineseName": {
"query": "德懷特",
"operator": "and"
}
}
},
{
"match_phrase": {
"about": "1915"
}
}
]
}
}
}
# 也可以這樣寫
GET user/_search
{
"query": {
"bool": {
"should": [
{
"range": {
"age": {
"gte": 49,
"lte": 53
}
}
},
{
"must": [
{
"match": {
"chineseName": {
"query": "德懷特",
"operator": "and"
}
}
},
{
"match_phrase": {
"about": "1915"
}
}
]
}
]
}
}
}
查詢英文不區(qū)分大小寫的原因:Elasticsearch在構(gòu)建倒排索引的時(shí)候會(huì)將所有的英文字母轉(zhuǎn)為小寫,在進(jìn)行查詢的時(shí)候,分詞器會(huì)將所有的關(guān)鍵詞分詞并轉(zhuǎn)為小寫去倒排索引中進(jìn)行匹配
查詢指定的Field
# 查詢指定的Field
GET user/_search
{
"_source":["about","graduationSchool.chinese"],
"query": {
"match": {
"chineseName": "懷特"
}
}
}
keyword數(shù)據(jù)類型
keyword表示不分詞,原始數(shù)據(jù)長(zhǎng)啥樣,匹配的時(shí)候就得寫啥樣,大小寫、長(zhǎng)度、內(nèi)容必須完全一致
completion數(shù)據(jù)類型
自動(dòng)補(bǔ)全(前綴匹配)對(duì)于一個(gè)搜索引擎或者電商網(wǎng)站來(lái)說(shuō)都是使用最為頻繁的一個(gè)功能,所以對(duì)性能要求是極高,所以ES6針對(duì)這種情況專門設(shè)計(jì)了一種數(shù)據(jù) completion, 會(huì)將用戶搜索過(guò)所有的數(shù)據(jù)都存儲(chǔ)到內(nèi)存中,下次再進(jìn)行前綴匹配的直接從內(nèi)存中找;它還能做到預(yù)先加載。要想做前綴匹配功能數(shù)據(jù)類型必須是completion。
在ES中有這樣一個(gè)規(guī)則,索引一旦有數(shù)據(jù),是不能調(diào)整 mapping的。因此我們只能通過(guò)刪除原來(lái)的mapping,重新定義新的mapping的形式來(lái)修改mapping,由于mapping的定義方式比較復(fù)雜,我們可以如下步驟定義新的mapping:
1. 先規(guī)劃好索引中將要存放的數(shù)據(jù),然后根據(jù)規(guī)劃隨便寫入一個(gè)樣例數(shù)據(jù),目的是讓借助于ES本身的能力來(lái)自動(dòng)幫我們 生成一個(gè)mapping;
2. 通過(guò) GET example/_mapping 來(lái)獲取樣例數(shù)據(jù)自動(dòng)生產(chǎn)的mapping, 然后拷貝"mappings" : {}這一部分的內(nèi)容,將對(duì)應(yīng)字段的type修改為completion
3. 通過(guò)DELETE example刪除之前的索引;
4. 通過(guò)put example{mappings" : {}}將修改好的 "mappings" : {}這一部分的內(nèi)容重新設(shè)置;
5. 導(dǎo)入正規(guī)數(shù)據(jù);
重新設(shè)置mapping的語(yǔ)法
PUT user
{
"mappings" : {
"properties" : {
"about" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"address" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"age" : {
"type" : "long"
},
"chineseName" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"firstname" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"graduationSchool" : {
"properties" : {
"chinese" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"englishName" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"lastname" : {
"type" : "completion",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"services" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
使用自動(dòng)補(bǔ)全(匹配前綴查詢功能)
# 使用自動(dòng)補(bǔ)全(匹配前綴查詢功能)
# false表示返回結(jié)果中無(wú)_source內(nèi)容:"_source": false,
# _source也可以指定只顯示所指定的字段:"_source": "name",
# 或者使用數(shù)組表示指定多個(gè)字段:"_source": ["name","level"],
GET user/_search
{
"_source": false,
"suggest": {
"lastName_suggest":{ #lastName_suggest為自定義名稱
"prefix":"美國(guó)",
"completion":{
"field":"graduationSchool.chinese"
}
}
}
}
自動(dòng)補(bǔ)全(前綴匹配)即從索引庫(kù)中匹配perfix:"value"前綴以value開(kāi)頭的倒排索引,再根據(jù)倒排索引匹配到對(duì)應(yīng)的document
Analysis分詞與Analyzer分詞器
Analysis(只是一個(gè)概念),文本分析就是把全文本轉(zhuǎn)換成一系列單詞(term/token)的過(guò)程,也叫分詞。Analysis 是通過(guò)分詞器(Analyzer) 來(lái)實(shí)現(xiàn)的,可使用 ES 內(nèi)置的分析器或者按需定制化分析器。數(shù)據(jù)寫入的時(shí)候會(huì)將詞條進(jìn)行分詞,數(shù)據(jù)查詢的時(shí)候也會(huì)使用相同的分詞器對(duì)所查詢語(yǔ)句進(jìn)行分詞。最終分詞的結(jié)果會(huì)存在于倒排索引庫(kù)的字典中
ES內(nèi)置分詞器:
- Standard Analyzer - 默認(rèn)分詞器,按詞切分,小寫處理
- Simple Analyzer - 按照非字母切分(符號(hào)被過(guò)濾),小寫處理
- Stop Analyzer - 小寫處理,停用詞過(guò)濾(the ,a,is)
- Whitespace Analyzer - 按照空格切分,不轉(zhuǎn)小寫
- Keyword Analyzer - 不分詞,直接將輸入當(dāng)做輸出
- Pattern Analyzer - 正則表達(dá)式,默認(rèn) \W+
- Language - 提供了 30 多種常見(jiàn)語(yǔ)言的分詞器
- Customer Analyzer - 自定義分詞器
分詞器的組成
Character Filters
Character Filters:針對(duì)原始文本處理,比如去除 html 標(biāo)簽
Tokenizer
Tokenizer:按照規(guī)則切分為單詞,比如按照空格切分、按標(biāo)點(diǎn)符號(hào)切分
Token Filters
Token Filters:將切分的單詞進(jìn)行加工,比如大寫轉(zhuǎn)小寫,刪除 stopwords(停用詞),增加同義語(yǔ)
# 使用ES內(nèi)置分詞器
GET _analyze
{
"analyzer": "standard",
"text": "2 Hello WORLD,The world is beautiful!"
}
ES內(nèi)置的分詞器并不能很好的支持中文的分詞,所以我么需要安裝中文分詞器。常見(jiàn)的中文分詞器:IK分詞器和拼音分詞器
IK分詞器
IK分詞器支持自定義詞庫(kù),支持熱更新分詞字典。安裝步驟如下:
第一步:下載zip包,下載路徑為:https://github.com/medcl/elasticsearch-analysis-ik/releases
第二步:將下載好的zip包解壓后放在Elasticsearch的plugins目錄下(/usr/share/elasticsearch/plugins)
# 方式一:通過(guò)docker cp命令
docker cp /data/elasticsearch/analyzer/ik elasticsearch:/usr/share/elasticsearch/plugins
# 方式二:通過(guò)數(shù)據(jù)卷
# 在原來(lái)的docker-compose.yml文件中加入
volumes:
- /data/elasticsearch/analyzer:/usr/share/elasticsearch/plugins
第三步:刪除原來(lái)的elasticsearch容器和kibana容器,執(zhí)行docker-compose up命令
docker rm elasticsearch容器ID kibana容器ID
docker-compose up
IK分詞插件對(duì)應(yīng)的分詞器有以下幾種:ik_smart
和ik_max_word
# 中文分詞演示
GET _analyze
{
"analyzer": "ik_smart",
"text": "Docker菜鳥教程"
}
拼音分詞器
拼音分詞器的安裝步驟:
第一步:下載ZIP包,下載路徑為:https://github.com/medcl/elasticsearch-analysis-pinyin/releases
第二步:將下載好的zip包解壓后放在Elasticsearch的plugins目錄下(/usr/share/elasticsearch/plugins)
# 方式一:通過(guò)docker cp命令
docker cp /data/elasticsearch/analyzer/pinyin elasticsearch:/usr/share/elasticsearch/plugins
# 方式二:通過(guò)數(shù)據(jù)卷
# 在原來(lái)的docker-compose.yml文件中加入
volumes:
- /data/elasticsearch/analyzer:/usr/share/elasticsearch/plugins
第三步:刪除原來(lái)的elasticsearch容器和kibana容器,執(zhí)行docker-compose up命令
docker rm elasticsearch容器ID kibana容器ID
docker-compose up
# pinyin分詞器演示
GET _analyze
{
"analyzer": "pinyin",
"text": "Docker菜鳥教程"
}
在索引上使用分詞器
# 在mapping中為需要使用分詞器的field設(shè)置分詞器
# analyzer表示該field所要使用的分詞器
# search_analyzer:keyword表示在查詢?cè)揻ield的時(shí)候查詢的關(guān)鍵詞不被分詞處理,如果不寫默認(rèn)采用該字段所使用的分詞器對(duì)查詢的關(guān)鍵詞進(jìn)行分詞
PUT user/_mapping
{
"properties" : {
"about" : {
"type" : "text",
"analyzer":"ik_max_word",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"address" : {
"type" : "text",
"analyzer":"ik_max_word",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
自定義分詞器
第一步:根據(jù)規(guī)則導(dǎo)入一個(gè)樣例數(shù)據(jù),目的是讓elasticsearch幫我們生成mapping
PUT example
{
"field_1":"value",
"field_2":"value",
"field_3":"value",
"field_4":"value"
}
第二步:查看mapping,并復(fù)制修改mapping
GET example/_mapping
第三步:刪除樣例數(shù)據(jù)生成的index
DELETE example
第四步:自定義分詞器
# 自定義analyzer中的屬性都是和分詞器分詞的順序?qū)?yīng):先走Character Filters,再走Tokenizer,最后走Token Filter
# char_filter:規(guī)則決定Character Filters組件對(duì)原始文本處理時(shí)處理的規(guī)則--原始文本如何處理
# tokenizer:規(guī)則決定Tokenizer組件分詞的規(guī)則--如何分詞
# filter:規(guī)則決定Token Filter對(duì)分詞后的詞語(yǔ)處理的規(guī)則--分詞后如何處理(這里采用的是自定義規(guī)則)
# type:表示該分詞器使用的基礎(chǔ)分詞器(分完詞后再進(jìn)行拼音分詞)
# keep_full_pinyin:type后面的屬性是對(duì)基礎(chǔ)分詞器的屬性的設(shè)置
PUT user
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer":{
"char_filter":"html_strip",
"tokenizer":"keyword",
"filter":"my_filter"
}
},
"filter": {
"my_filter":{
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_none_chinese": false,
"keep_original": true
}
}
}
}
}
# 或者
PUT user/_settings
{
"analysis": {
"analyzer": {
"my_analyzer":{
"char_filter":"html_strip",
"tokenizer":"keyword",
"filter":"my_filter"
}
},
"filter": {
"my_filter":{
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_none_chinese": false,
"keep_original": true
}
}
}
}
char_filter可以選擇的規(guī)則有以下這些規(guī)則
tokenizer可以選擇的規(guī)則有以下這些規(guī)則
第五步:驗(yàn)證自定義分詞器效果
GET user/_analyze
{
"analyzer": "my_analyzer",
"text":"Elasticsearch 平臺(tái) — 大規(guī)模查找實(shí)時(shí)答案"
}
第六步:PUT examplet{“mappings”:{}}添加mapping
PUT user/_mapping
{
"properties" : {
"about" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"address" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"age" : {
"type" : "long"
},
"chineseName" : {
"type" : "completion",
"analyzer":"my_analyzer",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"firstname" : {
"type" : "completion",
"analyzer":"my_analyzer",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"graduationSchool" : {
"properties" : {
"chinese" : {
"type" : "completion",
"analyzer":"my_analyzer",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"englishName" : {
"type" : "completion",
"analyzer":"my_analyzer",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"lastname" : {
"type" : "completion",
"analyzer":"my_analyzer",
"search_analyzer": "keyword",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"services" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
# 第七步:添加數(shù)據(jù)-(批量添加、logstash添加)
# _bulk的操作,行為和請(qǐng)求體數(shù)據(jù) 都是不能換行的。
POST user/_bulk
{"index":{"_id":1}}
{"firstname" : "Douglas","lastname" : "MacArthur","chineseName" : "道格拉斯·麥克阿瑟","age":48,"address":"American","graduationSchool" : {"englishName" : "The United States Military Academy(West Point)","chinese" : "美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about" : "1899年,麥克阿瑟考入西點(diǎn)軍校。第一次世界大戰(zhàn)期間晉升為上校并前往法國(guó)參戰(zhàn)。1919年6月,被任命為西點(diǎn)軍校校長(zhǎng)。20世紀(jì)20-30年代擔(dān)任陸軍參謀長(zhǎng)。第二次世界大戰(zhàn)時(shí)期歷任美國(guó)遠(yuǎn)東軍司令,西南太平洋戰(zhàn)區(qū)盟軍司令。1944年麥克阿瑟被授予陸軍五星上將軍銜。1945年9月2日以盟軍最高統(tǒng)帥的身份主持了對(duì)日本的受降儀式并代表同盟國(guó)簽字。二戰(zhàn)后出任駐日盟軍最高司令長(zhǎng)官、遠(yuǎn)東軍司令等職,對(duì)日本實(shí)行了一系列改革,之后出任“聯(lián)合國(guó)軍”總司令。1952年,參與美國(guó)共和黨總統(tǒng)初選,但未勝出。1964年4月5日,麥克阿瑟因膽結(jié)石去世,終年84歲。","services":"陸軍"}
{"index":{"_id":2}}
{"firstname" : "William Daniel","lastname" : "Leahy","chineseName":"威廉·丹尼爾·萊希","age" : 32,"address" : "American", "graduationSchool" : {"englishName" : "The United States Annapolis Naval Academy","chinese" : "美國(guó)亞那波里斯海軍學(xué)院"},"about" : "威廉·丹尼爾·萊希1897年畢業(yè)於美國(guó)亞那波里斯海軍學(xué)院,第一次世界大戰(zhàn)期間指揮一艘海軍運(yùn)輸艦,同當(dāng)時(shí)任海軍部助理部長(zhǎng)的富蘭克林·羅斯福結(jié)成生死之交。歷任軍械局局長(zhǎng)(1927~1931)、航行局局長(zhǎng)(1933~1935)、美國(guó)海軍作戰(zhàn)部長(zhǎng)(1937年-1939年)、1936年晉升為海軍上將。1939年因年邁退休。數(shù)月后,被羅斯??偨y(tǒng)任命為波多黎各總督(1939年-1940年)、接著出任駐維希法國(guó)大使(1941年-1942年),美國(guó)參戰(zhàn)后,擔(dān)任新設(shè)置的總統(tǒng)參謀長(zhǎng)職務(wù)(1942年-1949年)并主持美國(guó)參謀長(zhǎng)聯(lián)席會(huì)議,和英帝國(guó)總參謀長(zhǎng)阿蘭布魯克子爵一起決定盟國(guó)大戰(zhàn)略。1944年成為美國(guó)歷史上首位獲五星上將軍銜的軍官。次年隨羅斯福參加雅爾塔會(huì)議。1945年4月羅斯福去世后,他在杜魯門總統(tǒng)任內(nèi)繼任原職。1949年退休,寫有戰(zhàn)爭(zhēng)回憶錄《身歷其境》(I Was There,1950)。","services":"海軍"}
{"index":{"_id":3}}
{"firstname" : "Dwight David","lastname" : "Eisenhower","chineseName" : "德懷特·戴維·艾森豪威爾","age" : 53,"address" : "American","graduationSchool" : {"englishName" : "The United States Military Academy(West Point)","chinese" : "美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about" : "艾森豪威爾在1915年畢業(yè)于西點(diǎn)軍校。1944年任歐洲盟軍最高司令,晉升為五星上將。1952年競(jìng)選總統(tǒng)獲勝,成為第34任美國(guó)總統(tǒng),1956年再次競(jìng)選獲勝,蟬聯(lián)總統(tǒng)。1950年前后任美國(guó)哥倫比亞大學(xué)校長(zhǎng)。1969年3月28日,艾森豪威爾在華盛頓因心臟病去世,享年78歲。","services":"陸軍"}
{"index":{"_id":4}}
{"firstname" : "James Alward","lastname" : "Van Fleet","chineseName":"詹姆斯·奧爾沃德·范佛里特","age" : 47,"address" : "American","graduationSchool":{"englishName":"The United States Military Academy(West Point)","chinese":"美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about":"1915年美國(guó)西點(diǎn)軍校畢業(yè),晉升中尉。1916年參加墨西哥邊界之戰(zhàn)。1918年參加第一次世界大戰(zhàn)。第二次世界大戰(zhàn)期間任第4師第8步兵團(tuán)團(tuán)長(zhǎng)、第23軍第90師師長(zhǎng)、第三軍軍長(zhǎng)。1947年任第一集團(tuán)軍副司令。同年任美駐歐洲司令部副總司令。1948年在希臘任聯(lián)合軍事先頭增援集團(tuán)軍司令。1951年在朝鮮戰(zhàn)爭(zhēng)中任美國(guó)第八集團(tuán)軍司令。1953年以上將軍銜退休","services":"陸軍"}
{"index":{"_id":5}}
{"firstname" : "Mark Wayne","lastname" : "Clark","chineseName":"馬克·韋恩·克拉克","age" : 49,"address" : "American","graduationSchool":{"englishName":"The United States Military Academy(West Point)","chinese":"美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about":"美國(guó)四星上將,第二次世界大戰(zhàn)期間的美國(guó)第五集團(tuán)軍司令與朝鮮戰(zhàn)爭(zhēng)時(shí)的聯(lián)合國(guó)軍指揮官。","services":"陸軍"}
{"index":{"_id":6}}
{"firstname" : "Matthew Bunker","lastname" : "Ridgway","chineseName":"馬修·邦克·李奇微","age" : 47,"address" : "American","graduationSchool":{"englishName":"The United States Military Academy(West Point)","chinese":"美國(guó)陸軍學(xué)院(西點(diǎn)軍校)"},"about":"美國(guó)著名軍事家、陸軍上將。1895年,李奇微出生于美國(guó)弗吉尼亞州門羅堡,曾經(jīng)參加過(guò)朝鮮戰(zhàn)爭(zhēng)。1993年7月26日,李奇微去世。","services":"陸軍"}
第七步:驗(yàn)證
GET user/_search
{
"suggest": {
"chineseName_suggest": {
"prefix":"dan",
"completion":{
"field":"chineseName"
}
}
}
}
Logstash導(dǎo)入MySQL中的數(shù)據(jù)
第一步:在logstash的confing目錄下創(chuàng)建一個(gè).conf文件,寫入以下內(nèi)容:
input {
jdbc {
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_connection_string => "jdbc:mysql://localhost:3306/es?useSSL=false&serverTimezone=UTC"
jdbc_user => es
jdbc_password => "123456"
#啟用追蹤,如果為true,則需要指定tracking_column
use_column_value => false
#指定追蹤的字段,
tracking_column => "id"
#追蹤字段的類型,目前只有數(shù)字(numeric)和時(shí)間類型(timestamp),默認(rèn)是數(shù)字類型
tracking_column_type => "numeric"
#記錄最后一次運(yùn)行的結(jié)果
record_last_run => true
#上面運(yùn)行結(jié)果的保存位置
last_run_metadata_path => "mysql-position.txt"
statement => "SELECT * FROM news where tags is not null"
#表示每天的 17:57分執(zhí)行
schedule => " 0 57 17 * * *"
}
}
filter {
mutate {
split => { "tags" => ","}
}
}
output {
elasticsearch {
#每一個(gè)document對(duì)應(yīng)的_id的生成規(guī)則
document_id => "%{id}"
#每一個(gè)document對(duì)應(yīng)的type
document_type => "_doc"
#生成的index名稱
index => "news"
hosts => ["http://localhost:9200"]
}
stdout{
codec => rubydebug
}
}
第二步:將MySQL的驅(qū)動(dòng)jar包放入logstash的/logstash-core/lib/jars
目錄下
第三步:在logstash的bin目錄下執(zhí)行l(wèi)ogstash命令
logstash -f ../confing/example.conf
定制化高亮顯示
需要在查詢語(yǔ)句中添加highlight屬性規(guī)則
GET user/_search
{
"query": {
"match": {
"about": {
"query": "陸軍上將",
"operator": "and"
}
}
},
"highlight": {
"fields": {
"about":{
"pre_tags": "<span>",
"post_tags": "</span>"
}
}
},
"from": 0,
"size": 10
}
GET user/_search
{
"query": {
"match_phrase": {
"about": "陸軍上將"
}
},
"highlight": {
"fields": {
"about": {
"pre_tags": "<em>"
, "post_tags": "</em>"
}
}
}
}
提高搜索的準(zhǔn)確度–自定義詞庫(kù)
因?yàn)樵谖覀儗?shí)際的業(yè)務(wù)中,有很多專業(yè)的業(yè)務(wù)詞庫(kù)并沒(méi)有被IK收錄,那么就會(huì)導(dǎo)致一個(gè)問(wèn)題,數(shù)據(jù)在索引進(jìn)ES的時(shí)候,不會(huì)將業(yè)務(wù)的專有詞庫(kù)作為一個(gè)名詞,會(huì)拆分為一個(gè)個(gè)的字,導(dǎo)致搜索的準(zhǔn)確度會(huì)受到很大的影響,所以我們需要在IK中添加一些針對(duì)業(yè)務(wù)的專有詞庫(kù)。
配置本地自定義詞庫(kù)–靜態(tài)添加
第一步:在ik分詞器的confing目錄中創(chuàng)建一個(gè)自定義詞庫(kù)文件夾analysis
第二步:在analysis文件下創(chuàng)建一個(gè).dic文件custom_analysis.dic
第三步:在custom_analysis.dic添加詞語(yǔ)(custom_analysis.dic文件中的詞語(yǔ)都不會(huì)再被分詞),在custom_analysis.dic中加入自己的業(yè)務(wù)詞庫(kù)(一個(gè)詞是一行
)
第四步:編輯ik分詞器confing目錄下的IKAnalyzer.cfg.xml文件,將自己定義的詞庫(kù)配置進(jìn)ik分詞的詞庫(kù)
將自己的文件路徑配置進(jìn)去:<entry key="ext_dict">analysis/custom_analysis.dic</entry>
<?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">analysis/custom_analysis.dic</entry>
<!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->
<entry key="ext_stopwords"></entry>
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展停止詞字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
第五步:驗(yàn)證自定義詞庫(kù)
GET user/_analyze
{
"analyzer": "ik_max_word",
"text": ["詞庫(kù)中的詞"]
}
無(wú)論是何種方式,只能影響后續(xù)數(shù)據(jù)索引進(jìn) ES的分詞,改變不了之前已經(jīng)寫入到ES中的數(shù)據(jù)的分詞;那么我們需要將這些文檔重新索引,執(zhí)行如下的命令:
第六步:更新索引庫(kù)–重新索引
# 自定義詞庫(kù)
POST user/_update_by_query
{
"query": {
"bool": {
"must": [
{
"match": {
"about": "將"
}
},
{
"match": {
"about": "軍"
}
}
]
}
}
}
第七步:重啟Elasticsearch
這種靜態(tài)添加的方式存在弊端在于,每次添加新的業(yè)務(wù)詞庫(kù),都需要重啟ES服務(wù),所以就有了動(dòng)態(tài)添加的方式。
配置遠(yuǎn)程自定義詞庫(kù)–動(dòng)態(tài)添加
第一步:需要一個(gè)服務(wù)器,可以是nginx,也可以自己搭建;但是根據(jù)IK分詞器的要求,這個(gè)服務(wù)器需要在請(qǐng)求頭中返回 LastModified、ETag. 現(xiàn)在我們以 nginx 為例來(lái)說(shuō)明:
第二步:在 nginx的/html 目錄下新建一個(gè)創(chuàng)建一個(gè)analysis.txt文件,要注意該文件的編碼是 utf-8
第三步:在analysis.txt文件中加入業(yè)務(wù)詞庫(kù),一詞一行
第四步:將analysis.txt 文件的訪問(wèn)路徑配置到 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ò)展字典 -->
<entry key="ext_dict"></entry>
<!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->
<entry key="ext_stopwords"></entry>
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!-- http://192.168.213.142/analysis.txt最終會(huì)訪問(wèn)到nginx的/html/analysis.txt文件 -->
<entry key="remote_ext_dict">http://192.168.213.142/analysis.txt</entry>
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展停止詞字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
第五步:驗(yàn)證自定義詞庫(kù)
GET user/_analyze
{
"analyzer": "ik_max_word",
"text": ["詞庫(kù)中的詞"]
}
無(wú)論是何種方式,只能影響后續(xù)數(shù)據(jù)索引進(jìn) ES的分詞,改變不了之前已經(jīng)寫入到ES中的數(shù)據(jù)的分詞;那么我們需要將這些文檔重新索引,執(zhí)行如下的命令:
第六步:更新索引庫(kù)–重新索引
# 自定義詞庫(kù)
POST user/_update_by_query
{
"query": {
"bool": {
"must": [
{
"match": {
"about": "將"
}
},
{
"match": {
"about": "軍"
}
}
]
}
}
}
這種動(dòng)態(tài)添加的好處在于,每次添加新的業(yè)務(wù)詞庫(kù),不需要重新啟動(dòng)服務(wù)器
添加近義詞
在實(shí)際的業(yè)務(wù)中,很多時(shí)候在搜索的時(shí)候,有些內(nèi)容可能不同的人表述方式不同,或者在專業(yè)或者非專業(yè)領(lǐng)域表述的方式不同,但是我們要達(dá)到相同的搜索效果,所以需要添加近義詞,例如:
1. 例如美團(tuán)搜索 住宿,會(huì)檢索出 酒店、民宿、賓館等。
2. 例如搜索 娛樂(lè),會(huì)檢索出 游樂(lè)場(chǎng)、影院、沐足等。
第一步:在Elasticsearch的confing目錄下創(chuàng)建一個(gè)analysis/synonym.txt近義詞文件
第二步:在 synonym.txt 文件中加入如下內(nèi)容:
酒店,民宿,賓館=>住宿
炒菜具,烹飪具,鍋具,鍋鏟
娛樂(lè),游樂(lè)場(chǎng),影院,沐足
旅游景點(diǎn),黃山,泰山,華山
對(duì)于第一行,在數(shù)據(jù)寫入到 ES,將"酒店,民宿,賓館"都映射為"住宿",這樣導(dǎo)致的后果就是可以通過(guò)"住宿"可以收到"酒店,民宿,賓館",但是單獨(dú)去搜索"酒店",蒸具,"酒店"就搜不到了。
對(duì)于第二行,“炒菜具,烹飪具,鍋具,鍋鏟"是"炒菜具"的同義詞,在搜索"炒菜具"的時(shí)候,可以把"炒菜具,烹飪具,鍋具,鍋鏟"都搜索出來(lái);搜"烹飪具"可以搜索到"烹飪具,鍋具,鍋鏟”;搜索"鍋具",可以搜索到"鍋具,鍋鏟",搜"鍋鏟"就只有"鍋鏟"。
第三步:自定義分詞器,將近義詞詞庫(kù)與分詞器綁定
# synonyms_path會(huì)默認(rèn)去Elasticsearch的confing目錄下尋找該文件
PUT example/_settings
{
"analysis": {
"analyzer": {
"example_analyzer": {
"tokenizer": "ik_max_word",
"filter": "example_synonym"
}
},
"filter": {
"example_synonym": {
"type": "synonym",
"synonyms_path": "analysis/synonym.txt"
}
}
}
}
第四步:構(gòu)建mapping,在mapping中指定對(duì)應(yīng)的field使用的分詞器。
# 可將第三步和第四步進(jìn)行合并
PUT example
{
"settings": {
"analysis": {
"analyzer": {
"example_analyzer": {
"tokenizer": "ik_max_word",
"filter": "example_synonym"
}
},
"filter": {
"example_synonym": {
"type": "synonym",
"synonyms_path": "analysis/synonym.txt"
}
}
}
},
"mappings": {
"properties" : {
"id" : {
"type" : "long"
},
"price" : {
"type" : "float"
},
"small_pic" : {
"type" : "keyword"
},
"title" : {
"type" : "text",
"analyzer": "example_analyzer",
"search_analyzer": "ik_smart"
}
}
}
}
第五步:寫入數(shù)據(jù)。然后可以執(zhí)行近義詞的搜索。
GET spu/_analyze
{
"analyzer": "insert_analyzer",
"text": ["柳巖"]
}
第六步,每次添加新的近義詞,都需要重新啟動(dòng)ES服務(wù),還需要對(duì)后寫入的數(shù)據(jù)重新索引;
Spring Boot整合Elasticsearch
第一步:導(dǎo)入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
第二步:在容器中注入RestHighLevelClient
@Configuration
public class ESConfing extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("192.168.11.132:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
第四步:使用相關(guān)的API
@RestController
@RequestMapping("/user")
@CrossOrigin("*")
public class CompletionController {
@Autowired
private RestHighLevelClient restHighLevelClient;
@RequestMapping("/firstNameCompletion")
public ResultPageBean<SearchResultModel> getFirstNameCompletion(String prefix) throws IOException {
Request request = new Request("GET","user/_search");
request.setJsonEntity(String.format("{" +
" \"_source\": false, " +
" \"suggest\": {" +
" \"chineseName_suggest\": {" +
" \"prefix\":\"%s\"," +
" \"completion\":{" +
" \"field\":\"chineseName\"" +
" }" +
" }" +
" }" +
"}",prefix));
RestClient lowLevelClient = restHighLevelClient.getLowLevelClient();
Response response = lowLevelClient.performRequest(request);
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity);
JSONArray options = JSONObject.parseObject(result).getJSONObject("suggest").getJSONArray("chineseName_suggest").getJSONObject(0).getJSONArray("options");
List<SearchResultModel> resultList = options.stream().map(ele -> {
String text = ((JSONObject) ele).getString("text");
return new SearchResultModel(text);
}).collect(Collectors.toList());
ResultPageBean<SearchResultModel> stringResultPageBean = new ResultPageBean<SearchResultModel>(200,10,resultList);
return stringResultPageBean;
}
@GetMapping("/allUserInfo")
public ResultPageBean<JSONObject> getAllUserInfo() throws IOException {
Request request = new Request("GET","/user/_search");
Response response = restHighLevelClient.getLowLevelClient().performRequest(request);
HttpEntity entity = response.getEntity();
String resutl = EntityUtils.toString(entity);
JSONArray hitsArray = JSONObject.parseObject(resutl).getJSONObject("hits").getJSONArray("hits");
List<JSONObject> sourceList = hitsArray.stream().map(ele -> ((JSONObject) ele).getJSONObject("_source")).collect(Collectors.toList());
ResultPageBean<JSONObject> jsonObjectResultPageBean = new ResultPageBean<>(200, 10, sourceList);
return jsonObjectResultPageBean;
}
}
參考1文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-816471.html
參考2文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-816471.html
到了這里,關(guān)于Elasticsearch的安裝和使用——Docker的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!