ElasticSearch 是什么赋续?
ElasticSearch 是一個(gè)基于Lucene的分布式、RESTful 風(fēng)格红淡、近實(shí)時(shí)的搜索和數(shù)據(jù)分析引擎庐舟。以下簡(jiǎn)稱(chēng)ES
開(kāi)發(fā)語(yǔ)言: Java
支持客戶端:Java、.NET(C#)色冀、PHP潭袱、Python、Apache Groovy锋恬、Ruby 等屯换,支持REST風(fēng)格調(diào)用
為什么選擇ES?
市場(chǎng)類(lèi)似類(lèi)似產(chǎn)品:Solr
市場(chǎng)地位: 目前已取代Solr成為使用最多最受歡迎的搜索分析引擎
ElasticSearch 和 Solr的取舍:
- ElasticSearch 晚于Solr ,借鑒了Solr的成功經(jīng)驗(yàn) 更注重?cái)U(kuò)展性与学,搜索實(shí)時(shí)性更高
todo - Solr在搜索靜態(tài)數(shù)據(jù)時(shí)性能更高,ES在更新索引時(shí)依然可以維持穩(wěn)定的搜索性能
-
ES 彤悔,Solr搜索指數(shù)對(duì)比
image.png
image.png
image.png
ES架構(gòu)
作為入門(mén),先不用過(guò)多去研究架構(gòu)層次的內(nèi)容,先上一張圖,大概了解一下即可
1. Gateway是ES用來(lái)存儲(chǔ)索引的文件系統(tǒng),支持多種類(lèi)型索守。
2. Gateway的上層是一個(gè)分布式的lucene框架晕窑。
3. Lucene之上是ES的模塊,包括:索引模塊卵佛、搜索模塊杨赤、映射解析模塊等
4. ES模塊之上是 Discovery、Scripting和第三方插件截汪。Discovery是ES的節(jié)點(diǎn)發(fā)現(xiàn)模塊望拖,不同機(jī)器上的ES節(jié)點(diǎn)要組成集群需要進(jìn)行消息通信,集群內(nèi)部需要選舉master節(jié)點(diǎn)挫鸽,這些工作都是由Discovery模塊完成说敏。支持多種發(fā)現(xiàn)機(jī)制,如 Zen 丢郊、EC2盔沫、gce、Azure枫匾。Scripting用來(lái)支持在查詢語(yǔ)句中插入javascript架诞、python等腳本語(yǔ)言,scripting模塊負(fù)責(zé)解析這些腳本干茉,使用腳本語(yǔ)句性能稍低谴忧。ES也支持多種第三方插件。
5. 再上層是ES的傳輸模塊和JMX.傳輸模塊支持多種傳輸協(xié)議,如 Thrift沾谓、memecached委造、http,默認(rèn)使用http均驶。JMX是java的管理框架昏兆,用來(lái)管理ES應(yīng)用。
6. 最上層是ES提供給用戶的接口妇穴,可以通過(guò)RESTful接口和ES集群進(jìn)行交互爬虱。
ES常用使用場(chǎng)景
站內(nèi)搜索: 比如各類(lèi)電商,論壇,新聞,ERP網(wǎng)站,站內(nèi)搜索功能一般都由ES或Solr支持
-
日志分析: 常用組合ELK,既 ES + Logstash (最新用Beats) + Kibana
監(jiān)控、統(tǒng)計(jì)腾它、日志類(lèi)時(shí)間序的數(shù)據(jù)存儲(chǔ)和分析跑筝、可視化,ELK可以完美支持
image.png 作為NoSQL Json數(shù)據(jù)庫(kù)
作為NoSQL數(shù)據(jù)庫(kù),ES比Mogo讀寫(xiě)性能更強(qiáng)大,可以支持PB級(jí)數(shù)據(jù).
對(duì)地理位置等數(shù)據(jù)支持更好,可以方便的計(jì)算經(jīng)緯度坐標(biāo)的距離,坐標(biāo)范圍查詢等功能BI系統(tǒng)
BI系統(tǒng)也成商業(yè)智能,主要是通過(guò)數(shù)據(jù)挖掘,數(shù)據(jù)分析提供有價(jià)值的商業(yè)決策
ES的海量數(shù)據(jù)處理能力和多樣,快速的查詢,統(tǒng)計(jì)可以提供強(qiáng)大的支撐
ES 常用概念
1瞒滴、文檔 (document)
文檔是ES索引和搜索數(shù)據(jù)的最小單位曲梗。
它擁有靈活的結(jié)構(gòu)。文檔不依賴于預(yù)先定義的模式逛腿。并非所有的文檔都需要擁有相同的字段,它們不受限于同一個(gè)模式仅颇。
不過(guò)當(dāng)用于搜索時(shí),為了提高性能通常會(huì)定義好每個(gè)字段的類(lèi)型,并使用mapping定義文檔結(jié)構(gòu).
2单默、類(lèi)型 (type)
類(lèi)型是文檔的邏輯容器,類(lèi)似于表格是行的容器忘瓦。在不同的類(lèi)型中搁廓,最好放入不同結(jié)構(gòu)的文檔。例如耕皮,可以用一個(gè)類(lèi)型存放商品的數(shù)據(jù)境蜕,而另一個(gè)類(lèi)型存放用戶的數(shù)據(jù)。
PS: 7.X版本已徹底放棄type, 提倡每個(gè)索引存放單一類(lèi)型數(shù)據(jù),不再有type的概念了
3凌停、索引 (index)
索引是映射類(lèi)型的容器粱年。一個(gè)Elasticsearch索引是獨(dú)立的大量的文檔集合。 每個(gè)索引存儲(chǔ)在磁盤(pán)上的同組文件中罚拟,索引存儲(chǔ)了所有映射類(lèi)型的字段台诗,還有一些設(shè)置。
當(dāng)你插入一個(gè)文檔時(shí),ES默認(rèn)會(huì)自動(dòng)為每一個(gè)自動(dòng)匹配一個(gè)類(lèi)型,作為小白直接使用也是可以的, 但是正式環(huán)境使用時(shí)一般都需要根據(jù)業(yè)務(wù)需求自定義mapping去定義索引字段及字段類(lèi)型才能發(fā)揮出更高的性能
4赐俗、映射(mapping)
所有文檔在寫(xiě)入索引前都將被分析拉队,用戶可以設(shè)置一些參數(shù),決定如何將輸入文本分割為詞條阻逮,哪些詞條應(yīng)該被過(guò)濾掉粱快,或哪些附加處理有必要被調(diào)用(比如移除HTML標(biāo)簽)。這就是映射扮演的角色:存儲(chǔ)分析鏈所需的所有信息。
示例:
{
"doccenter_test" : {
"mappings" : {
"DcDoc" : {
"properties" : {
"catalogId" : {
"type" : "keyword"
},
"docConvertstatus" : {
"type" : "keyword"
},
"docCreateddate" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss"
},
"docDowncount" : {
"type" : "integer"
},
"docId" : {
"type" : "keyword"
},
"docName" : {
"type" : "text",
"analyzer" : "ik_max_word"
}
}
}
}
}
}
ES 數(shù)據(jù)類(lèi)型
看了上邊的mapping定義,是不是發(fā)現(xiàn)其中有數(shù)據(jù)類(lèi)型的定義了?但是ES里具體有哪些類(lèi)型呢?我們還是得像學(xué)Java一樣一個(gè)個(gè)過(guò)一遍.以后定義mapping方能知其然并知其所以然
鑒于本文只做一個(gè)概述,大家了解一下即可,每個(gè)類(lèi)型的具體用法和特性咱們先不做討論
* 字符型:string
* 數(shù)字型:long:64位存儲(chǔ) , integer:32位存儲(chǔ) , short:16位存儲(chǔ) , byte:8位存儲(chǔ) , double:64位雙精度存儲(chǔ) , float:32位單精度存儲(chǔ)
* 日期型:date
* 布爾型: boolean
* 二進(jìn)制型:binary
##### 復(fù)雜數(shù)據(jù)類(lèi)型(Complex datatypes)
* 數(shù)組類(lèi)型:數(shù)組類(lèi)型不需要專(zhuān)門(mén)指定數(shù)組元素的type事哭,例如:
* 字符型數(shù)組: [ "one", "two" ]
* 整型數(shù)組:[ 1, 2 ]
* 數(shù)組型數(shù)組:[ 1, [ 2, 3 ]] 等價(jià)于[ 1, 2, 3 ]
* 對(duì)象數(shù)組:[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }]
* 對(duì)象類(lèi)型:* object *用于單個(gè)JSON對(duì)象漫雷;
* 嵌套類(lèi)型:* nested *用于JSON數(shù)組;
##### 地理位置類(lèi)型(Geo datatypes)
* 地理坐標(biāo)類(lèi)型:* geo_point *用于經(jīng)緯度坐標(biāo)慷蠕;
* 地理形狀類(lèi)型:* geo_shape *用于類(lèi)似于多邊形的復(fù)雜形狀珊拼;
##### 專(zhuān)業(yè)類(lèi)型(Specialised datatypes)
* IPv4 類(lèi)型:* ip *用于IPv4 地址;
* Completion 類(lèi)型:* completion *提供自動(dòng)補(bǔ)全建議流炕;
* Token count 類(lèi)型:* token_count *用于統(tǒng)計(jì)做了標(biāo)記的字段的index數(shù)目澎现,該值會(huì)一直增加,不會(huì)因?yàn)檫^(guò)濾條件而減少每辟。
* [mapper-murmur3]:通過(guò)插件剑辫,可以通過(guò) *murmur3 *來(lái)計(jì)算index的 hash 值;
* 附加類(lèi)型(Attachment datatype):采用[mapper-attachments] 插件渠欺,可支持* attachments *索引妹蔽,例如Microsoft Office 格式,Open Document 格式挠将,ePub, HTML 等胳岂。
第一個(gè)HelloWorld(6.8版本演示)
書(shū)讀百遍不如動(dòng)手一遍,基礎(chǔ)概念學(xué)完了,咱們寫(xiě)一個(gè)HelloWorld 找找感覺(jué)
首先你得安裝好你的ES和Kibana,安裝比較簡(jiǎn)單這里就不多說(shuō)了
然后復(fù)習(xí)一下自從學(xué)了RESTFUL以來(lái),從來(lái)就沒(méi)有使用過(guò)的幾個(gè)http請(qǐng)求格式
1)GET:獲取請(qǐng)求對(duì)象的當(dāng)前狀態(tài)。
2)POST:改變對(duì)象的當(dāng)前狀態(tài)舔稀。ES中插入文檔會(huì)自動(dòng)生成ID
3)PUT:創(chuàng)建一個(gè)對(duì)象乳丰。ES中用于指定ID進(jìn)行插入
4)DELETE:銷(xiāo)毀對(duì)象。
5)HEAD:請(qǐng)求獲取對(duì)象的基礎(chǔ)信息内贮。
打開(kāi)Kibana,進(jìn)入這個(gè)頁(yè)面
自定義mapping 創(chuàng)建一個(gè)索引,
你會(huì)發(fā)現(xiàn)ES的使用就是這么簡(jiǎn)單
PUT music
{
"mappings": {
"_doc" : {
"properties" : {
"name" : {
"type": "text"
},
"author":{
"type":"keyword"
}
}
}
}
}
有了索引就可以嘗試一下程序員終極技能了:增刪改查
#創(chuàng)建索引
PUT music
{
"mappings": {
"musicType" : {
"properties" : {
"name" : {
"type": "text"
},
"author":{
"type":"text"
}
}
}
}
}
#插入文檔
PUT music/musicType/10000
{
"name":"牧馬城市",
"author":"誰(shuí)誰(shuí)誰(shuí)"
}
#根據(jù)id查詢
GET music/musicType/10000
#修改一下歌名
PUT music/musicType/10000
{
"name":"牧馬城市",
"author":"毛不易"
}
#換個(gè)姿勢(shì)查詢所有
GET /music/musicType/_search
{
"query":{
"match_all": {}
}
}
#匹配查詢
GET /music/musicType/_search
{
"query":{
"match": {
"name":"牧馬"
}
}
}
#刪除文檔
DELETE music/musicType/10000
#換個(gè)姿勢(shì)刪除
POST music/musicType/_delete_by_query
{
"query":{
"match": {
"name":"牧馬"
}
}
}
#練習(xí)完畢,刪除索引
DELETE music
分詞器
學(xué)會(huì)了增刪改查,理所當(dāng)然要找個(gè)實(shí)際需求練練手了,這個(gè)時(shí)候我們就需要接觸到ES的另一個(gè)概念:分詞
ES之所以能夠?qū)Υ罅课臋n,大段文字進(jìn)行快速檢索,依靠的就是對(duì)文檔進(jìn)行分詞,然后生成倒排索引. 數(shù)據(jù)庫(kù)知識(shí)比較扎實(shí)的應(yīng)該對(duì)倒排索引都不陌生, 它記錄了每個(gè)詞的關(guān)聯(lián)文檔,頻率等信息從而在我們需要的時(shí)候能夠快速檢索. 具體理論可以參考以下文章
https://www.cnblogs.com/cjsblog/p/10327673.html
而所謂分詞就是按照一定規(guī)則對(duì)大段的文字進(jìn)行拆分,從而得到n多個(gè)有意義的詞匯产园。
ES默認(rèn)的分詞規(guī)則是針對(duì)英文的,也就是按照空格拆分.比如:我愛(ài)你祖國(guó),會(huì)被分詞為 我,愛(ài),你,祖,國(guó)五個(gè)詞. 這對(duì)中文來(lái)說(shuō)跟沒(méi)有分詞一樣,毫無(wú)用處。 所以就有了針對(duì)中文的專(zhuān)門(mén)的分詞器:IK Analazer
IK分詞器在中文分詞領(lǐng)域是毫無(wú)爭(zhēng)議的No1 , 甚至強(qiáng)到都沒(méi)人知道老二是誰(shuí)
我們想使用它也很簡(jiǎn)單,只需要去下載ES相同版本,放在 %ES_HOME%/config 目錄下
重啟ES即可
然后我們就可以在定義mapping的時(shí)候或者搜索時(shí)指定分詞器
PUT music
{
"mappings": {
"musicType" : {
"properties" : {
"name" : {
"type": "text",
"analyzer": "ik_smart"
},
"author":{
"type":"text",
"analyzer": "ik_max_word"
}
}
}
}
}
大家會(huì)發(fā)現(xiàn)我使用了ik_smart, ik_max_word兩種分詞器.
這其實(shí)是IK提供的兩種模式,ik_smart 是精簡(jiǎn)的分詞模式,同樣的文字分出的詞匯比較少, ik_max_word則會(huì)盡可能多的對(duì)詞進(jìn)行切分
我們可以使用Kibana進(jìn)行簡(jiǎn)單的測(cè)試就可以明白其中的不同
GET _analyze
{
"analyzer":"ik_smart",
"text":"我是一個(gè)中國(guó)人"
}
分詞結(jié)果:
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "是",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "一個(gè)",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "中國(guó)人",
"start_offset" : 4,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 3
}
]
}
GET _analyze
{
"analyzer":"ik_max_word",
"text":"我是一個(gè)中國(guó)人"
}
分詞結(jié)果
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "是",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "一個(gè)中國(guó)",
"start_offset" : 2,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "一個(gè)",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "一",
"start_offset" : 2,
"end_offset" : 3,
"type" : "TYPE_CNUM",
"position" : 4
},
{
"token" : "個(gè)中",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 5
},
{
"token" : "個(gè)",
"start_offset" : 3,
"end_offset" : 4,
"type" : "COUNT",
"position" : 6
},
{
"token" : "中國(guó)人",
"start_offset" : 4,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "中國(guó)",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 8
},
{
"token" : "國(guó)人",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 9
}
]
}
ES 6.8 IK分詞器bug
但是再好的代碼也有bug, 我們?cè)谏弦粋€(gè)項(xiàng)目中就遇到了一個(gè)6.8版本的bug,據(jù)說(shuō)7.0已經(jīng)修復(fù). 在這里還是記錄一下,畢竟我們使用的是6.8版本
這個(gè)bug就是在插入某些特定詞語(yǔ)的時(shí)候IK分詞器因?yàn)榻馕鰡?wèn)題會(huì)報(bào)以下錯(cuò)誤:
"startOffset must be non-negative, and endOffset must be >= startOffset, and offsets must not go backwards startOffset=2,endOffset=3,lastStartOffset=3 for field 'description'"
比如:2018年口腔助理考試考點(diǎn):肉芽腫性唇炎的特點(diǎn)
解決方案也很簡(jiǎn)單:
- 升級(jí)版本
- 將報(bào)錯(cuò)的詞語(yǔ)添加到自定義分詞規(guī)則中
顯然第二中方案更簡(jiǎn)單一點(diǎn)
ES學(xué)習(xí)路線
看完上邊這么多,希望大家能對(duì)ES有一個(gè)基本的輪廓,當(dāng)然這只是個(gè)入門(mén),路漫漫其修遠(yuǎn)兮,附一張ES的學(xué)習(xí)路線圖,供大家參考