- es 6.0 開始不推薦一個
index
下多個type
的模式,並且會在 7.0 中完全移除。在 6.0 的index
下是無法創建多個type
的,type
帶來的字段類型衝突和檢索效率下降的問題,導致了type
會被移除。(5.x到6.x) -
_all
字段也被捨棄了,使用copy_to
自定義聯合字段。(5.x到6.x) -
type:text/keyword
來決定是否分詞,index: true/false
決定是否索引(2.x到5.x) -
analyzer
來單獨設定分詞器(2.x到5.x)
創建索引
我們新建一個名news
的索引
:設定默認分詞器爲ik分詞器用來處理中文
使用默認名 _doc 定義 type
關閉_source存儲(用來驗證 store 選項)
title 不存儲 author 不分詞 content 存儲
PUT /news
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1,
"index": {
"analysis.analyzer.default.type" : "ik_smart"
}
},
"mappings": {
"_doc": {
"_source": {
"enabled": false
},
"properties": {
"news_id": {
"type": "integer",
"index": true
},
"title": {
"type": "text",
"store": false
},
"author": {
"type": "keyword"
},
"content": {
"type": "text",
"store": true
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd hh:mm:ss"
}
}
}
}
}
# 查看創建的結構
GET /news/_mapping
驗證分詞器是否生效
# 驗證分詞插件是否生效
GET /_analyze
{
"analyzer": "ik_smart",
"text": "我熱愛祖國"
}
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "我熱愛祖國"
}
# 索引的默認分詞器
GET /news/_analyze
{
"text": "我熱愛祖國!"
}
# 指定字段 分詞器將根據字段屬性做相應分詞處理
# author 爲 keyword 是不會做分詞處理
GET /news/_analyze
{
"field": "author"
"text": "我熱愛祖國!"
}
# title 的分詞結果
GET /news/_analyze
{
"field": "title"
"text": "我熱愛祖國!"
}
添加文檔
用於演示,後面的查詢會以這些文檔爲例。
POST /news/_doc
{
"news_id": 1,
"title": "我們一起學旺叫",
"author": "才華橫溢王大貓",
"content": "我們一起學旺叫,一起旺旺旺旺旺,在你面撒個嬌,哎呦旺旺旺旺旺,我的尾巴可勁兒搖",
"created_at": "2019-03-26 11:55:20"
}
{
"news_id": 2,
"title": "我們一起學貓叫",
"author": "王大貓不會被分詞",
"content": "我們一起學貓叫,還是旺旺旺旺旺,在你面撒個嬌,哎呦旺旺旺旺旺,我的尾巴可勁兒搖",
"created_at": "2019-03-26 11:55:20"
}
{
"news_id": 3,
"title": "實在編不出來了",
"author": "王大貓",
"content": "實在編不出來了,隨便寫點數據做測試吧,旺旺旺",
"created_at": "2019-03-26 11:55:20"
}
檢索數據
match_all
即無檢索條件獲取全部數據
#無條件分頁檢索 以 news_id 排序
GET /news/_doc/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 2,
"sort": {
"news_id": "desc"
}
}
因爲我們關掉了_source
字段,即 ES
只會對數據建立倒排索引
,不會存儲其原數據,所以結果裏沒有相關文檔原數據內容。關掉的原因主要是想演示highlight
機制。
match
普通檢索,很多文章都說match
查詢會對查詢內容進行分詞,其實並不完全正確,match
查詢也要看檢索的字段type
類型,如果字段類型本身就是不分詞的keyword
(not_analyzed
),那match
就等同於term
查詢了。
我們可以通過分詞器explain
一下字段會被如何處理:
GET /news/_analyze
{
"filed": "title",
"text": "我會被如何處理呢?分詞?不分詞?"
}
查詢
GET /news/_doc/_search
{
"query": {
"match": {
"title": "我們會被分詞"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
通過highlight
我們可以將檢索到的關鍵詞以高亮的方式返回上下文內容,如果關閉了_source
就得開啓字段的store
屬性存儲字段的原數據,這樣才能做高亮處理,不然沒有原內容了,也就沒辦法高亮關鍵詞了
multi_match
對多個字段進行檢索,比如我想查詢title
或content
中有我們
關鍵詞的文檔,如下即可:
GET /news/_doc/_search
{
"query": {
"multi_match": {
"query": "我們是好人",
"fields": ["title", "content"]
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
match_phrase
這個需要認證理解一下,match_phrase
,短語查詢,何爲短語查詢呢?簡單來說即被查詢的文檔字段中要包含查詢內容
被分詞解析後的所有關鍵詞
,且關鍵詞
在文檔中的分佈距離差offset
要滿足slop
設定的閾值。slop
表徵可以將關鍵詞
平移幾次來滿足在文檔中的分佈,如果slop
足夠的大,那麼即便所有關鍵詞
在文檔中分佈的很離散,也是可以通過平移滿足的。
content: i love china
match_phrase: i china
slop: 0//查不到 需要將 i china 的 china 關鍵詞 slop 1 後變爲 i - china 才能滿足
slop: 1//查得到
測試實例
# 先看下查詢會被如何解析分詞
GET /news/_analyze
{
"field": "title",
"text": "我們學"
}
# reponse
{
"tokens": [
{
"token": "我們",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "學",
"start_offset": 2,
"end_offset": 3,
"type": "CN_CHAR",
"position": 1
}
]
}
# 再看下某文檔的title是被怎樣建立倒排索引的
GET /news/_analyze
{
"field": "title",
"text": "我們一起學旺叫"
}
# reponse
{
"tokens": [
{
"token": "我們",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "一起",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
},
{
"token": "學",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 2
},
...
]
}
注意position
字段,只有slop
的閾值大於
兩個不相鄰的關鍵詞的position
差時,才能滿足平移關鍵詞
至查詢內容短語
分佈的位置條件。
查詢內容被分詞爲:["我們", "學"]
,而文檔中["我們", "學"]
兩個關鍵字的距離爲 1
,所以,slop
必須大於等於1
,此文檔才能被查詢到。
使用查詢短語模式:
GET /news/_doc/_search
{
"query": {
"match_phrase": {
"title": {
"query": "我們學",
"slop": 1
}
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
查詢結果:
{
...
{
"_index": "news",
"_type": "_doc",
"_id": "if-CuGkBddO9SrfVBoil",
"_score": 0.37229446,
"highlight": {
"title": [
"<em>我們</em>一起<em>學</em>貓叫"
]
}
},
{
"_index": "news",
"_type": "_doc",
"_id": "iP-AuGkBddO9SrfVOIg3",
"_score": 0.37229446,
"highlight": {
"title": [
"<em>我們</em>一起<em>學</em>旺叫"
]
}
}
...
}
term
term
要理解只是不對查詢條件
分詞,作爲一個關鍵詞
去檢索索引。但文檔存儲時字段是否被分詞建立索引由_mappings
時設定了。可能有["我們", "一起"]
兩個索引,但並沒有["我們一起"]
這個索引,查詢不到。keyword
類型的字段則存儲時不分詞,建立完整索引,查詢時也不會對查詢條件
分詞,是強一致性的。
GET /news/_doc/_search
{
"query": {
"term": {
"title": "我們一起"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
terms
terms
則是給定多個關鍵詞
,就好比人工分詞
{
"query": {
"terms": {
"title": ["我們", "一起"]
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
滿足["我們", "一起"]
任意關鍵字的文檔都能被檢索到。
wildcard
shell
通配符查詢: ?
一個字符 *
多個字符,查詢倒排索引
中符合pattern
的關鍵詞。
查詢有兩個字符的關鍵詞的文檔
{
"query": {
"wildcard": {
"title": "??"
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
prefix
前綴查詢,查詢倒排索引
中符合pattern
的關鍵詞。
{
"query": {
"prefix": {
"title": "我"
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
regexp
正則表達式查詢,查詢倒排索引
中符合pattern
的關鍵詞。
查詢含有2 ~ 3 個字符的關鍵詞的文檔
{
"query": {
"regexp": {
"title": ".{2,3}"
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
bool
布爾查詢通過 bool
鏈接多個查詢組合:must
:必須全滿足must_not
:必須全不滿足should
:滿足一個即可
{
"query": {
"bool": {
"must": {
"match": {
"title": "絕對要有我們"
}
},
"must_not": {
"term": {
"title": "絕對不能有我"
}
},
"should": [
{
"match": {
"content": "我們"
}
},
{
"multi_match": {
"query": "滿足",
"fields": ["title", "content"]
}
},
{
"match_phrase": {
"title": "一個即可"
}
}
],
"filter": {
"range": {
"created_at": {
"lt": "2020-12-05 12:00:00",
"gt": "2019-01-05 12:00:00"
}
}
}
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
filter
filter
通常情況下會配合match
之類的使用,對符合查詢條件的數據進行過濾。
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"range": {
"created_at": {
"lt": "2020-12-05 12:00:00",
"gt": "2017-12-05 12:00:00"
}
}
}
}
}
}
或者單獨使用
{
"query": {
"constant_score" : {
"filter": {
"range": {
"created_at": {
"lt": "2020-12-05 12:00:00",
"gt": "2017-12-05 12:00:00"
}
}
}
}
}
}
多個過濾條件:2017-12-05 12:00:00 <= created_at < 2020-12-05 12:00:00 and news_id >= 2
{
"query": {
"constant_score" : {
"filter": {
"bool": {
"must": [
{
"range": {
"created_at": {
"lt": "2020-12-05 12:00:00",
"gt": "2017-12-05 12:00:00"
}
}
},
{
"range": {
"news_id": {
"gte": 2
}
}
}
]
}
}
}
}
}