文檔 Document
用戶存儲在es中的數據文檔
索引 Index
由具有相同字段的文檔列表
查看當前所有索引
GET /_cat/indince
節點Node
一個Elasticsearch的運行實例,是集群
集群master
elasticsearch
-----
Document
Json Object
數據類型:
字符串:text,keyword
數值型:long,integer,short,byte,double,float,half_float,scaled_float
布爾:boolean
日期:date
二進制:binary
范圍類型:integer_range,float_range,long_range,double_range,date_range
每個文檔都有唯一的id標識
-example
{
"remote_ip":"10.10.10.10",
...
}
元數據,用於標注文檔的相關信息
- _index:文檔所在的索引名
- _type: 文檔所在的類型名
- _id: 文檔唯一id
- _uid:組合id,由_type和_id組成(6.x _type不再起作用)
- _source:文檔的原始Json數據,可以從這里獲取每個字段的內容
- _all:整合所有字段內容到該字段,默認禁用
正排索引:
文檔id 文檔內容
1 es搜索引擎
2 php語言
3 搜索引擎的誕生
倒排索引:
單詞 文檔ID列表
es 1
搜索引擎 1,3
php 2
es自帶的分詞器
- Standard:
- 默認分詞器
特性:
- 按詞切分,支持多語言
- 小寫處理
- Simple:
特性:
- 按照非字母切分
- 小寫處理
- 會把下划線,單引號也都處理掉
- Whitespace
特性:
- 按照空格切分
- Stop
特性:
- 會把語氣助詞等修飾性的詞語都處理掉
- 其他和simple一直
- Keyword
特性:
- 不分詞, 直接將輸入作為一個單詞輸出
- Pattern
特性:
- 通過正則表達式自定義分割符
- 默認是\w+, 即非字詞的符號作為分隔符
- Language
- 提供了30+ 常見語言的分詞器
中文分詞:
難點 漢語中詞沒有一個形式上的分界符
常用分詞系統
- IK
- 實現中英文單詞的切分,支持IK_smart、 ik_maxword等模式
- 可自定義詞庫,支持熱更新分詞詞典
- jieba
- python中最流行的分詞系統,支持分詞和詞性標注
- 支持繁體分詞、自定義詞典、並行分詞等
自定義分詞
當自帶的分詞無法滿足需求時,可以自定義分詞
- 通過自定義 Character Filters、 Tokenizer 和 Token Filter 實現
Character Filters
- 在 Tokenizer 之前對原始文本進行處理,比如增加、刪除或替換字符等
-自帶的如下:
- HTML Strip 去除html標簽和轉換 html 實體
- Mapping 進行字符替換操作
- Pattern Replace 進行正則匹配替換
- 會影響后續 tokenizer 解析的postion 和offset 信息
Tokenizer
- 將原始文本按照一定規則切分為單詞(term or token)
- 自帶的如下:
- standard 按照單詞進行分割
- letter 按照費字符類進行分割
- whitespace 按照空格進行分割
- UAX URL Email 按照standard 分割, 但不會分割郵箱和url
- NGram 和Edge NGram 連詞分割
- Path Hierarchy 按照文件路徑進行切割
Token Filters
- 對於 tokenizer 輸出的單詞(term) 進行增加、刪除、修改等操作
- 自帶的如下:
- lowercase將所有term 轉換為小寫
- stop 刪除 stop words
- NGram 和 Edge NGram 連詞分割
- Synonym 添加近義詞的term
Mapping:
1、類似數據庫的表結構定義,主要作用是:
-定義Index下的字段名(Filed Name)
-定義字段的類型, 比如數值型、字符串型、布爾型等
-定義倒排索引相關的配置,比如是否索引、記錄position等
example:
GET /test_index/_mapping
{
"test_index":{ #索引名
"mappings":{
"doc":{ #type
"properties":{ #他下面指的是所有的字段
"age":{
"type":"integer"
},
"username":{
"type":"keyword" #不分詞
}
}
}
}
}
}
自定義Mapping的api:
request請求:
PUT my_index
{
"test_index":{ #索引名
"mappings":{
"doc":{ #type
"properties":{ #他下面指的是所有的字段
"age":{
"type":"integer"
},
"name":{
"type":"keyword" #不分詞
},
"title":"text"
}
}
}
}
}
response 返回結果 {"acknoeledged":ture,
"shards_acknowledged":true,
"index":"my_index"
}
Mapping中的字段類型一旦設定后,禁止直接修改,原因如下:
- Lucene 實現的倒排索引生成后不允許修改
重新建立新的索引,然后做reindex操作
允許新增字段
通過dynamic參數來控制字段的新增
- true(默認) 允許自動新增字段
- false 不允許自動新增字段,但是文檔可以 正常寫入,但無法對字段進行查詢等操作
- strict 文檔不能寫入, 報錯
PUT my_index
{
"mappings":{
"my_type":{
"dynamic":false,
"properties":{
"user":{
"properties":{
"name":{
"type": "text"
},
"social_networks":{
"dynamic":true,
"properties":{}
}
}
}
}
}
}
}
索引模板,Index Template, 主義熬用於在新建索引時自動應用預先設定的配置,簡化索引創建的操作步驟
- 可以設定索引的配置和mapping
- 可以有多個模板,根據order設置,order大的覆蓋小的配置
index
- 控制當前字段是否索引,默認為true,即記錄索引,false不記錄,即不可搜索
index_options 用於控制倒排索記錄的內容,有如下4中配置
- docs只記錄 doc id
- freqs 記錄 doc id 和 term frequencies
- positions 記錄 doc id、 term frequencies 和 term position
- offsets 記錄 doc id、 term frequencies、 term position 和character offsets
text類型默認配置為positons,其他默認為docs
記錄內容越多,占用空間越大
null_value
-當字段遇到null值時的處理策略,默認為null,即空值,此時es會忽略該值。可以通過設定該值設定字段的默認值
PUT my_index
{
"mappings":{
"my_type":{
"properties":{
"status_code":{
"type": "keyword",
"null_value":"NULL" #設定默認值為NULL
}
}
}
}
}
數據類型
核心數據類型
- 字符串型: text、 keyword
- 數值型 long、 integer、short、byte、double、float、half_float、scaled_float
- 日期類型 date
- 布爾類型 boolean
- 二進制類型 binary
- 范圍類型 integer_range、float_range、long_range、double_range、date_range
復雜數據類型
- 數組類型 array
- 對象類型 object
- 嵌套類型 nested object
地理位置數據類型:
- geo_point
- geo_shape
專用類型
- 記錄ip地址 ip
- 實現自動補全 comletion
- 記錄分詞數 token_cout
- 記錄字符串hash值 murmur3 #通過插件實現
- percolator
- join #父子查詢
es是依靠JSON文檔的字段類型來實現自動識別字段類型,支持的類型如下:
JSON類型 es類型
null 忽略
boolean boolean
浮點類型 float
整數 long
object object
array 由第一個非null值得類型決定
string 匹配為日期則設為date 類型(默認開啟),匹配為數字的話設為float或long類型(默認關閉),設為te xt類型,並附帶keyword的子字段
日期的自動識別可以自行配置日期格式,以滿足各種需求
-默認是 ["strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
- strict_date_optional_time 是ISO datetime的格式,完整格式類似下面:
- YYYY-MM0DDThh:mm:ssTZD(eg 1997-07-16T19:20:30+01:00)
- dynamic_date_formats 可以自定義日期類型
- date_detection 可以關閉日期自動識別的機制
自定義日期識別格式
PUT my_index
{
"mappings":{
"my_type":{
"dynamic_date_formats":["MM/dd/yyyy"]
}
}
}
關閉日期自動識別機制
PUT my_index
{
"mappings":{
"my_type":{
"date_detection":false
}
}
}
字符串是數字時,默認不會自動識別為整型,因為字符串中出現數字是完全合理的
- numeric_detection 可以開啟字符串中數字的自動識別,如下所示:
PUT my_index
{
"mappings":{
"my_type":{
"numeric_detection":true
}
}
}
Search API
實現對es中存儲的數據進行查詢分析,endpoint為_search,如下所示
GET /_search
GET /my_index/_search
GET /my_index1,my_index2/_search
GET /my_*/_search 指定索引查詢,可以一次查詢多個
查詢主要有兩種形式
- URI Search
- 操作簡單,方便通過命令行測試
- 僅包含部分查詢語法
- Request Body Search
-es 提供的完備查詢語法Query DSL(Domain Specific language)
URI Search:
GET /MY_INDEX/_search?q=user:alfred
Request Body Search:
GET /my_index/_search
{
"query":{
"term":{"user":"alfred"}
}
}
Request Body Search
將查詢語句通過http request body 發送到es, 主要包含如下參數
- query符合 Query DSL 語法的查詢語句
- from,size
- timeout
- sort
- ...
符合Query DSL 查詢語法的查詢語句
GET /my_index/_search
{
"query":{
"term":{"user":"alfred"}
}
}
Query DSL
基於JSON定義的查詢語言,主要包含如下兩種類型:
- 字段類查詢
如 term,match,range等, 只針對某一個字段進行查詢
- 復合查詢
如bool查詢等,包含一個或多個字段類查詢或者復合查詢語句
---字段類查詢
字段類查詢主要包括一下兩類:
-全文匹配
針對 text 類型的字段進行全文檢索,會對查詢語句先進行分詞處理,如 match,match_phrase等query類型
-單詞匹配
不會對查詢語句做分詞處理,直接去匹配字段的倒排索引,如term,terms,range等query類型
match query 流程
GET test_search_index/_search
#operator參數可以控制但此件的匹配關系,可選項為or和and
{
"query":{
"match":{
"username":{
"query":"java ruby",
"operator":"and"
}
}
}
}
GET test_search_index/_search
#通過minimum_should_match 參數可以控制需要匹配的單詞數
{
"query":{
"match":{
"job":{
"query":"java ruby enager",
"minimum_should_match":"2"
}
}
}
}
對查詢語句分詞
java ruby (對整個詞做一次拆分)
java ruby
根據username的倒排索引進行匹配算分 (二者一致操作)
算法規則(TF/IDF BM25)
匯總得分
根據得分排序,返回匹配文檔
相關性算分
相關性算分是指文檔與查詢語句間的相關度,英文為relevance
-通過倒排索引可以獲取與查詢語句相匹配的文檔列表
相關性算分的幾個重要概念如下:
Term Frequency(TF)詞頻,即單詞在改文檔中出現的次數。詞頻越高,相關度越高
Document Frequency(DF)文檔頻率,即單詞出現的文檔數
Inverse Documnet Frequency(IDF)逆向文檔頻率,與文檔頻率相反,簡單理解為1/DF。即單詞出現的文檔數越少,相關度越高
Field-length Norm 文檔越短,相關性越高
query查詢時,加explain可以看到算分,排序的計算公式
Match Phrase Query 按照順序匹配
GET test_search_index/_search
{
"query":{
"match_phrase":{
"job":"java engineer"
}
}
}
GET test_search_index/_search
{
"query":{
"match_phrase":{
"job":{
"query":"java engineer",
#可以間隔一個字段查詢結構
"shop",1
}
}
}
}
Query String Query
類似於URI Search中的q參數查詢
GET test_search_index/_search
{
"query":{
"query_string":{
"default_field":"username"
"query":"alfred AND way"
}
}
}
GET test_search_index/_search
{
#參數里加profile會顯示查詢語句
"profile":true,
"query":{
"query_string":{
"fields":["username","job"]
"query":"alfred OR (java AND ruby)"
}
}
}
Simple Query String Query
類似Query String, 但是會忽略錯誤的查詢語法,並且僅支持部分查詢語法
其常用的邏輯符號如下,不能使用AND、OR、NOT等關鍵詞:
+ 代指 AND
| 代指 OR
- 代指NOT
Term Query
將查詢語句作為整個單詞進行查詢,即不對查詢語句做分詞處理,如下所示:
GET test_search_index/_search
{
"query":{
"term":{
"username":"alfred"
}
}
}
GET test_search_index/_search
{
"query":{
"terms":{
"username":[
"alfred",
"way"
]
}
}
}
Range Query
范圍查詢主要針對數值和日期類型,如下所示:
GET test_search_index/_search
{
"query":{
"range":{
"age":{
"gte":10,
"lte":20
}
}
}
}
關鍵字: gt 大於
gte 大於等於
lt 小於
lte 小於等於
GET test_search_index/_search
{
"query":{
"range":{
"brith":{
"gte":"1990-01-01"
}
}
}
}
Query DSL - 復合查詢
復合查詢是指包含字段類查詢或復合查詢的類型,主要包括以下幾類:
- constant_score query
該查詢將其內部的查詢結果文檔得分都設定為1或者boost的值
- 多用於結合bool查詢實現自定義得分
GET test_search_index/_search
{
"query":{
"constant_score":{
"filter":{ #只能有一個filter
"match":{
"username":"alfred"
}
}
}
}
}
- bool query
布爾查詢由一個或多個布爾子句組成,他們都支持數組的,主要包含如下4個:
filter 只過濾符合條件的文檔,不計算相關性得分
must 文檔必須符合must中的所有條件,會影響相關性得分
must_not 文檔必須不符合must_not 中的所有條件
should 文檔可以符合should中的條件,會影響相關性得分
Filter查詢值只過濾符合條件的文檔,不會進行相關性算分
es正對filter會有智能緩存,因此其執行效率很高
做簡單匹配查詢且不考慮算分時,推薦使用filter替代query等
GET test_search_index/_search
{
"query":{
"bool":{
"filter":[
{
"term":{
"username":"alfred"
}
}
]
}
}
}
Must
兩個match query文檔最終得分為這兩個查詢得分加和
GET test_search_index/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"username":"alfred"
}
},
{
"match":{
"job":"specialist"
}
}
]
}
}
}
Must_not
GET test_search_index/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"username":"alfred"
}
}
],
"must_not":[
{
"match":{
"job":"ruby"
}
}
]
}
}
}
Should 使用分兩種情況:
bool查詢中只包含should,不包含must查詢
bool查詢中同時包含should和must查詢
只包含should時,文檔必須滿足至少一個條件
minimum_should_match 可以控制滿足條件的個數或者百分比
GET test_search_index/_search
{
"query":{
"bool":{
"should":[
{"term":{"job":"java"}},
{"term":{"job":"ruby"}},
{"term":{"job":"specialist"}}
],
"minimum_should_match":2
}
}
}
同時包含should和must時,文檔不必滿足should中的條件,但是如果滿足條件,會增加相關性得分
GET test_search_index/_search
{
"query":{
"bool":{
"must":[
{"term":{"username":"alfred"}},
],
"should":[
{"term":{"job":"ruby"}}
]
}
}
}
query Context "VS" Filter Context
當一個查詢語句位於Query或者Filter上下文時,es執行的結果會不同,對比如下:
上下文類型:query
執行類型:查找與查詢語句最相關的文檔,對所有文檔進行相關性算分並排序
使用方法:· query
· bool中的must和should
上下文類型:Filter
執行類型:查找與查詢語句相匹配的文檔
使用方法:· query bool中的filter與must_not
· constant_score中的filter
- dis_max query
- function_score query
- boosting query
Count API
獲取符合條件的文檔數,endpoint為_count
(只獲取文檔數,不獲取文檔內容)
GET test_search_index/_count
{
"query":{
"match":{
"username":"alfred"
}
}
}
Source Filtering
過濾返回結果中_source中的字段,主要有如下幾種方式:
1. GET test_search_index/_search?_source=username
2. GET test_search_index/_search
{
"source":false
}
3. GET test_search_index/_search
{
"_source":["username","age"]
}
4. GET test_search_index/_search
{
"_source":{
"includes":"i*",
"excludes":"birth"
}
}