寫在前面
最近在學Elasticsearch ,
我相信只要是接觸過開發的都會聽過Elasticsearch或ELK這么一個技術。
主要用來做全文檢索或大數據分析等,之前一直處理了解狀態。
所以打算系統學學Elasticsearch ,這也算是我從零學習Elasticsearch的筆記吧。
1. Elasticsearch 術語介紹
1.1 文檔Document
- 用戶存儲在es中的數據文檔
- es存儲數據的最小單元
- 類比於數據庫一行數據
1.2 索引Index
-由相同字段的文檔列表組成
- 類比於數據庫中的表
ps: es6.0版本之前,索引下面可以新建多個Type,就把這個Index類比於database,
但是在,6.0版本之后,一個索引下面只能夠新建一個Type ,所以類比於表更合適
1.3 節點Node
- 一個ES的運行實例,是集群的基本單元
1.4 集群Cluser
- 有一個或多個節點組成,對外提供服務
2.Document 介紹
Document 主要就是一個Json Object
json對象有一些字段(Field)組成,常見數據類型:
- 字符串 :text , keywork
- 數值型 :long , integer , byte ,double , float , half_float(節省空間) , scaled_float(節省空間)
- 布爾: boolean
- 日期:date
- 二進制 : binary
- 范圍類型 (新的類型): integer_range , float_range , long_tange , double_range, date_range
注意:每一個文檔Document都有一個唯一的ID標識
- 可以自行指定
- es 自動生成
示例Document
{
"remote_ip":"123.207.226.36",
"user_name":"liuge",
"@timestamp":"2015-05-14T08:23:52.000Z",
"request_action":"GET",
"http_version":"1.1",
"response":"304",
"bytes":"0",
"referrer":"-",
"agent":"-"
}
每一個Document都有一個MetaData (元數據)
元數據:用於標注文檔的相關信息
- _index:文檔所在的索引名
- _type: 文檔所在的類型名
- _id:文檔的唯一ID
- _ uid:組合id,由_type和_id組成(6.X版本_type不再起作用)
- _source:文檔的原始Json數據,可以從這里獲取每一個字段的內容
- _all:整合所有字段的內容到該字段,默認禁用,不推薦
3.Index (索引) 介紹
類比於table,具有相同結構文檔的集合
- 每個索引都有自己的 mapping 定義 , 用於定義字段名和類型
一個集群可以有多個索引
3.RESTful API 介紹
es集群對外提供RESTful API:用戶操作集群中的數據
- 表現層 狀態 轉移
- URI 指定資源 ,如:Index ,Document
- Http Method 指明資源操作類型,如:GET,POST,PUT,DELETE等
與es集群資源進行交互的方式:
方式一:Curl命令行
curl -XPUT "HTTP://localhost:9200/ceshi/doc/1" -i -H "Content-Type:application/json" -d
'
{
"username":"liuge",
"job":"軟件開發"
}
'
方式二:Kibana DevTools
PUT /ceshi/doc/1
{
"useranme":"liuge",
"job":"軟件開發"
}
4.Mapping 介紹
Mapping設置,即如何定義數據字段和類型
==========Mapping的字段類型(Filed type)===========================
核心數據類型:
- 字符串 :text (會分詞), keywork(不會分詞)
- 數值型 :long , integer , byte ,double , float , half_float(節省空間) , scaled_float(節省空間)
- 布爾: boolean
- 日期:date
- 二進制 : binary
- 范圍類型 (新的類型): integer_range , float_range , long_tange , double_range, date_range
復雜的數據類型:
- 數組類型 array
- Object
- 嵌套類型 nested object
地理位置數據類型:
- geo_point
- geo_shape
專用類型:
- 記錄ip地址
- 實現自動補全completion
- 記錄分次數 token_count
- 記錄字符串 hash
- percolator
多字段特性:
- 允許對同一個字段采用不同的配置,比如分詞,常見的實現漢字實現拼音搜索
- 實現方式:在漢字中新增一個子字段為pinyin就可以
Kibana DevTools方式:(推薦)
4.1 自定義一個mapping
PUT accounts
{
"settings": {
"index": {
"number_of_shards" : 1,
"number_of_replicas" : 0
}
},
"mappings":{
"doc":{
"dynamic":false, # 設置不允許動態添加,結果是,可以插入未定義的字段,但是不能通過未定義字段值來進行查詢
"properties":{
"user": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"desc": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
}
}
}
上面代碼中,首先新建一個名稱為accounts的 Index
這三個字段都是中文,而且類型都是文本(text),所以需要指定中文分詞器,不能使用默認的英文分詞器。
Elastic 的分詞器稱為 analyzer。我們對每個字段指定分詞器。
"user": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
上面代碼中,analyzer是字段文本的分詞器,search_analyzer是搜索詞的分詞器。ik_max_word分詞器是插件ik提供的,可以對文本進行最大數量的分詞。
4.2 新增記錄,帶上id
PUT accounts/doc/1
{
"user": "張三",
"title": "工程師",
"desc": "數據庫管理"
}
新增記錄的時候,也可以不指定 Id,這時要改成 POST 請求
POST accounts/doc
{
"user": "李四",
"title": "工程師",
"desc": "系統管理"
}
4.3 刪除數據
DELETE accounts/doc/1
DELETE accounts
4.4更新記錄就是使用 PUT 請求,重新發送一次數據。
PUT accounts/doc/1
{
"user": "張三",
"title": "工程師",
"desc": "數據庫管理,軟件開發"
}
4.3 查詢數據
使用 GET 方法,直接請求/Index/Type/_search,就會返回所有記錄
GET accounts/doc/_search
/Index/Type/id ,返回指定id的記錄
GET accounts/doc/1
GET accounts/doc/_search
{
"query":{
"term":{
"_id":"1"
}
}
}
GET accounts/doc/_search
{
"query" : {
"match" : {
"desc" : "管理"
}
},
"from": 1,
"size": 1
}
上面代碼使用 Match 查詢,指定的匹配條件是desc字段里面包含"軟件"這個詞
Elastic 默認一次返回10條結果,可以通過size字段改變這個設置。
還可以通過from字段,指定位移。
上面代碼指定,從位置1開始(默認是從位置0開始),只返回一條結果。
邏輯運算or
GET accounts/doc/_search
{
"query" : { "match" : { "desc" : "軟件 系統" }}
}
邏輯運算and
GET accounts/doc/_search
{
"query": {
"bool": {
"must": [
{ "match": { "desc": "軟件" } },
{ "match": { "desc": "系統" } }
]
}
}
}
5 分詞介紹
5.1 Analysis
分詞是指將文本轉為一系列單詞的過程,也叫作文本分析
在es里面稱為Analysis
在es中專門負責分詞的組件叫做分詞器(Analyzer)
分詞器(Analyzer),es會自帶一部分詞器
- Character Filters
- 針對原始的文本進行處理,例如,去除html,a,p,div特殊符號等
- Tokenizer
- 將原始的文本按照一定的規則切分為單詞
- Token Filters
- 把Tokenizer再加工,大小寫轉換等,沒有實際意義的詞可以去掉,新增近義詞,同義詞等
ps:分詞執行的順序也是從上到下的
5.2 分詞API的使用
Analyze(分詞) API 使用
es提供的用於測試分詞的api接口,驗證分詞效果
- 可以直接指定分詞器(Analyzer)進行測試
POST _analyze
{
"analyzer":"standard", #這個測試用的standard分詞器是es自己帶的
"text":"Hello World!"
}
- 可以直接指定索引中的字段進行測試
POST test_index/_analyze
{
"field":"username", # 指定索引(表)的字段
"text":"hello world!"
}
- 可以自定義分析器進行測試
POST _analyze
{
"analyzer":"standard", #指明自己使用哪一個分詞器
"filter":["lowercase"], #指明filter處理為小寫
"text":"HEllo WOrld!"
}
5.3 預定義分詞器
es中自帶的分詞器
如下:分詞器前面講到,就是由三個部分組成,這里自帶的不同也是三個部分組成上不同
- standard Analyzer
- 默認分詞器,按照單詞的邊界切分
- Tokenizer 1.standard
- Token Filters : 1.standard 2.Loswer case 3.Stop(默認禁用)
- Simple Analyzer
- 切分規則。按照非字母切分,非字母的部分會被刪除
- Filters 1.Loswer case
- Whitespace Analyzer
- 按照空格進行切分
- Stop Analyzer
- 語氣助詞等修飾性詞語會被移除,比如,the ,an ,的,這那等
- 相比於Simple Analyzer 多了修飾性詞語的移除
- Filters 1.Loswer case 2.stop
- Keyword Analyzer
- 不進行分詞操作
- 原樣輸出,當你不想對文本做分詞操作的時候
- Pattern Analyzer
- 自定義切分的規則,正則匹配
- 默認是 \W+ ,即非字詞的符號作為分隔符,空格 ~ = ‘ 等特殊符號
- Language Analyzer
- 提供了30+ 常見語言的分詞器
中文分詞:是指將一句中文句子切分為一個個單獨的詞
在英文中,句子內單詞可以使用空格做明顯分隔,
在中文中,句子內的詞語是沒有分隔的
常見中文分詞系統:
- IK
- jieba
高階一點的:基於自然語言處理的分詞系統
- Hanlp
- THULAC
5.4 自定義分詞器
當自帶的分詞器無法滿足需求的時候,可以自定義分詞
通過自定義分詞的三個部分來實現:
- Character Filters
- Tokenizer
- Token Filters
5.4.1 Character Filters
- 針對原始的文本進行處理,例如,去除html,a,p,div特殊符號等
自帶的如下:
- HTML Script 去除html 標簽和轉換html實體
- Mapping 進行字符串的替換操作
- Pattern Replace進行正則匹配替換
會影響到Tokenizer解析position和offset
5.4.2 Tokenizer
-將原始文本按照一定規則切分為單詞
自帶的如下:
- standard按照單詞進行分割
- latter 按照非字符類進行分割
- whitespace 按照空格進行分割
- UAX URL Email 按照standard 分割 ,但不會分割郵箱和URL
- NGram 和Edge NGram 連詞分割
- Path Hierachy 按照文件路徑進行分割
測試:
POST _analyze{
"tokenizer":"path_hierachy",
"text":"/one/two/three"
}
5.4.3 Token Filters
- 將tokenizer 輸出的單詞(term )進行增加,刪除,修改等操作
自帶的如下:
- lowercase 將所有輸出的單詞轉換為小寫
- stop 刪除 stop words
- NGram 和 Edge Ngram 連詞分割
- Synonym 添加近義詞的term
重要,這里可以實現自動補全的功能
POST _analyze{
"text":"a Hello World!",
"tokenizer":"standard",
"filter":[
"stop", # 當有多個filter的時候,會依次執行
"lowercase",
{
"type":"ngram",
"min_gram":2,
"max_gram":4
}
]
}
5.5 自定義分詞的API
自定義分詞器在索引(具體表)中的設定:
PUT test_index{
"settings":{
"analysis":{
"char_filter":{},
"tokenizer":{},
"filter":{},
"analyzer":{}
}
}
}
demo
PUT testairbnb
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"autosuggest_analyzer": {
"filter": [
"lowercase",
"asciifolding",
"autosuggest_filter"
],
"tokenizer": "standard",
"type": "custom"
},
"ngram_analyzer": {
"filter": [
"lowercase",
"asciifolding",
"ngram_filter"
],
"tokenizer": "standard",
"type": "custom"
}
},
"filter": {
"autosuggest_filter": {
"max_gram": "20",
"min_gram": "1",
"token_chars": [
"letter",
"digit",
"punctuation",
"symbol"
],
"type": "edge_ngram"
},
"ngram_filter": {
"max_gram": "9",
"min_gram": "2",
"token_chars": [
"letter",
"digit",
"punctuation",
"symbol"
],
"type": "ngram"
}
}
}
}
},
"mappings": {
"doc": {
"dynamic": false,
"properties": {
"accommodates": {
"type": "integer"
},
"bathrooms": {
"type": "integer"
},
"bed_type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"bedrooms": {
"type": "integer"
},
"beds": {
"type": "integer"
},
"date_from": {
"type": "date",
"format": "yyyyMMdd"
},
"date_to": {
"type": "date",
"format": "yyyyMMdd"
},
"has_availability": {
"type": "boolean"
},
"host_image": {
"type": "keyword",
"ignore_above": 256,
"index": false
},
"host_name": {
"type": "text",
"analyzer": "autosuggest_analyzer",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"image": {
"type": "keyword",
"ignore_above": 256,
"index":false
},
"listing_url": {
"type": "keyword",
"ignore_above": 256
},
"location": {
"type": "geo_point"
},
"name": {
"type": "text",
"analyzer": "autosuggest_analyzer",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"property_type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"room_type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
上面分詞的配置中,能夠完全實現個性化設定
參考文章http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html
參考文章https://coding.imooc.com/class/chapter/181.html