Elasticsearch Query DSL
這里使用的 Elasticsearch
的版本為 7.12.1
。
1、基本概念
1.1 文檔(Document)
ElasticSearch 是面向文檔的,文檔是所有可搜索數(shù)據(jù)的最小單位,例如 MySQL 的一條數(shù)據(jù)記錄。
文檔會被序列化成為 json 格式,保存在 ElasticSearch 中。
每個文檔都有一個唯一 ID,例如 MySQL 中的主鍵 ID。
JSON文檔
一篇文檔包括了一系列的字段,例如數(shù)據(jù)中的一條記錄。
json 文檔,格式靈活,不需要預(yù)先定義格式。
文檔的元數(shù)據(jù)
GET /users/_search
_index
:文檔所屬的索引名
_type
:文檔所屬類型名
_id
:文檔唯一ID
_score
:相關(guān)性分數(shù)
_source
:文檔的原始JSON數(shù)據(jù)
1.2 索引
索引是文檔的容器,是一類文檔的結(jié)合,每個索引都有自己的mapping定義,用于定義包含的文檔的字段和類型
每個索引都可以定義 mapping 和 setting,mapping 是定義字段類型,setting 定義不同的數(shù)據(jù)分布。
GET /users
{
"users" : {
"aliases" : { },
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"gender" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"userName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"number_of_shards" : "1",
"provided_name" : "users",
"max_result_window" : "10000000",
"creation_date" : "1640698832865",
"number_of_replicas" : "1",
"uuid" : "w0nGfHpKQki7CqKYpzi7Kw",
"version" : {
"created" : "7120199"
}
}
}
}
}
1.3 Type
7.0之前,一個Index可以設(shè)置多個type,所以當時大多數(shù)資料顯示的都是type類型與數(shù)據(jù)庫的表。
7.0之后,一個索引只能創(chuàng)建一個type,_doc。
若不好理解,可以對比MySQL類比一下:
在es6.0以前,關(guān)系型數(shù)據(jù)庫的術(shù)語和Elasticsearch的術(shù)語的對應(yīng)關(guān)系:
關(guān)系型數(shù)據(jù)庫 | Elasticsearch |
---|---|
數(shù)據(jù)庫(database) | 索引(indices) |
表(tables) | 類型(types) |
行(rows) | 文檔(documents) |
列(columns) | 字段(fields) |
es6.0以后廢棄了類型這個概念,于是在es6.x和7.x,有如下對應(yīng)關(guān)系:
關(guān)系型數(shù)據(jù)庫 | Elasticsearch |
---|---|
表(tables) | 索引(indices) |
行(rows) | 文檔(documents) |
列(columns) | 字段(fields) |
1.4 節(jié)點
節(jié)點是一個ElasticSearch的實例,本質(zhì)上就是java的一個進程,一臺機器可以運行多個ElasticSearch進程,但生
產(chǎn)環(huán)境下還是建議一臺服務(wù)器運行一個ElasticSearch實例。
每個節(jié)點都有名字,通過配置文件配置,或者啟動時 -E node.name=node1。
每個節(jié)點在啟動后,會分配一個UID,保存在data目錄下。
主節(jié)點:master
默認情況下任何一個集群中的節(jié)點都有可能被選為主節(jié)點,職責是創(chuàng)建索引、刪除索引、跟蹤集群中的節(jié)點、決定
分片分配給相應(yīng)的節(jié)點。索引數(shù)據(jù)和搜索查詢操作會占用大量的內(nèi)存、cpu、io資源。因此,為了保證一個集群的
穩(wěn)定性,應(yīng)該主動分離主節(jié)點跟數(shù)據(jù)節(jié)點。
數(shù)據(jù)節(jié)點:data
看名字就知道是存儲索引數(shù)據(jù)的節(jié)點,主要用來增刪改查、聚合操作等。數(shù)據(jù)節(jié)點對內(nèi)存、cpu、io要求比較高,
在優(yōu)化的時候需要注意監(jiān)控數(shù)據(jù)節(jié)點的狀態(tài),當資源不夠的時候,需要在集群中添加新的節(jié)點。
負載均衡節(jié)點:client
該節(jié)點只能處理路由請求,處理搜索,分發(fā)索引等操作,該節(jié)點類似于Nginx的負載均衡處理,獨立的客戶端節(jié)點
在一個比較大的集群中是非常有用的,它會協(xié)調(diào)主節(jié)點、數(shù)據(jù)節(jié)點、客戶端節(jié)點加入集群的狀態(tài),根據(jù)集群的狀態(tài)
可以直接路由請求。
預(yù)處理節(jié)點:ingest
在索引數(shù)據(jù)之前可以先對數(shù)據(jù)做預(yù)處理操作,所有節(jié)點其實默認都是支持ingest操作的,也可以專門將某個節(jié)點配
置為ingest節(jié)點。
1.5 分片
分片分為主分片,副本分片。
主分片:用以解決數(shù)據(jù)水平擴展的問題,將數(shù)據(jù)分布到集群內(nèi)的所有節(jié)點上,一個分片是一個運行的Lucene(搜索
引擎)實例,主分片數(shù)在創(chuàng)建時指定,后續(xù)不允許修改,除非Reindex。
副本:用以解決數(shù)據(jù)高可用的問題,可以理解為主分片的拷貝,增加副本數(shù),還可以在一定程度上提高服務(wù)的可用
性。
在生產(chǎn)環(huán)境中分片的設(shè)置有何影響
分片數(shù)設(shè)置過小會導(dǎo)致無法增加節(jié)點實現(xiàn)水平擴展,單個分片數(shù)據(jù)量太大,導(dǎo)致數(shù)據(jù)重新分配耗時。假設(shè)你給索引
設(shè)置了三個主分片 ,這時你給集群加了幾個實例,索引也只能在三臺服務(wù)器上。
分片數(shù)設(shè)置過大導(dǎo)致搜索結(jié)果相關(guān)性打分,影響統(tǒng)計結(jié)果的準確性,單個節(jié)點上過多的分片,會導(dǎo)致資源浪費,同
時也會影響性能。
從ElasticSearch7.0開始,默認的主分片設(shè)置為1,解決了over-sharding的問題。
1.6 集群
查看集群健康狀態(tài)
GET _cluster/health
green
:主分片與副本都正常分配
yellow
:主分片全部正常分配,有副本分片未能正常分配
red
:有主分片未能分配,當服務(wù)器的磁盤容量超過85%時創(chuàng)建了一個索引
2、索引和文檔操作
2.1 查詢所有索引
GET /_cat/indices
GET /_cat/indices?v
# 查看狀態(tài)為綠色的索引
GET /_cat/indices?v&health=green
# 根據(jù)文檔數(shù)據(jù)倒序
GET /_cat/indices?v&s=docs.count:desc
# 查看索引具體字段
GET /_cat/indices/kibana*?pri&v&h=health,index,pri,rep,docs,count,mt
# 查看索引所占的內(nèi)存
GET /_cat/indices?v&h=i,tm&s=tm:desc
# 獲取索引狀態(tài)
GET /_cat/indices/movies?v&s=index
2.2 刪除某個索引
DELETE /test_index
2.3 新增索引
PUT /test_index
2.4 查看索引
GET /test_index
# 查看索引的文檔總數(shù)
GET /test_index/_count
2.5 創(chuàng)建映射
PUT /test_index/_mapping
{
"properties": {
"name": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart",
"store": false
},
"city": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart",
"store": false
},
"age": {
"type": "long",
"store": false
},
"description": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart",
"store": false
}
}
}
2.6 查看映射
GET /test_index/_mapping
2.7 新增文檔數(shù)據(jù)
自動生成id
POST /test_index/_doc
{
"name": "李四",
"age": 22,
"city": "深圳",
"description": "李四來自湖北武漢!"
}
指定id
PUT /test_index/_doc/1
{
"name": "Tom",
"age": 22,
"city": "深圳",
"description": "Tom來自美國!"
}
POST和PUT的區(qū)別:
使用PUT時需要在后面指定
_id
,比如PUT /dangdang/_doc/6
中的6
就是指定的_id
,POST可以指定也可以不指定。
POST和PUT指定
_id
之后如果該_id
存在的話就會先刪除原先的文檔,后添加新的文檔。
PUT /test_index/_create/1
{
"name": "Tom",
"age": 22,
"city": "深圳",
"description": "Tom來自美國!"
}
PUT /test_index/_create/10
{
"name": "Tom",
"age": 22,
"city": "深圳",
"description": "Tom來自美國!"
}
指定_create
,如果該id
的文檔已經(jīng)存在,操作失敗。
我們再增加幾條記錄:
#新增文檔數(shù)據(jù) id = 2
PUT /test_index/_doc/2
{
"name": "王五",
"age": 35,
"city": "深圳",
"description": "王五家住在深圳!"
}
#新增文檔數(shù)據(jù) id = 3
PUT /test_index/_doc/3
{
"name": "張三",
"age": 19,
"city": "深圳",
"description": "在深圳打工,來自湖北武漢"
}
#新增文檔數(shù)據(jù) id = 4
PUT /test_index/_doc/4
{
"name": "張三豐",
"age": 66,
"city": "武漢",
"description": "在武漢讀書,家在武漢!"
}
#新增文檔數(shù)據(jù) id = 5
PUT /test_index/_doc/5
{
"name": "趙子龍",
"age": 77,
"city": "廣州",
"description": "趙子龍來自深圳寶安,但是在廣州工作!"
}
#新增文檔數(shù)據(jù) id = 6
PUT /test_index/_doc/6
{
"name": "趙毅",
"age": 55,
"city": "廣州",
"description": "趙毅來自廣州白云區(qū),從事電子商務(wù)8年!"
}
#新增文檔數(shù)據(jù) id = 7
PUT /test_index/_doc/7
{
"name": "趙哈哈",
"age": 57,
"city": "武漢",
"description": "武漢趙哈哈,在深圳打工已有半年了,月薪7500!"
}
2.8 查看文檔
GET /test_index/_doc/1
2.9 修改數(shù)據(jù)
a、替換操作
更新數(shù)據(jù)可以使用之前的增加操作,這種操作會將整個數(shù)據(jù)替換掉,代碼如下:
#更新數(shù)據(jù),id=4
PUT /test_index/_doc/4
{
"name": "張三豐",
"description": "在武漢讀書,家在武漢!在深圳工作!"
}
使用GET命令查看:
#根據(jù)ID查詢
GET /test_index/_doc/4
b、更新操作
我們先使用下面命令恢復(fù)數(shù)據(jù):
#恢復(fù)文檔數(shù)據(jù) id=4
PUT /test_index/_doc/4
{
"name": "張三豐",
"age": 66,
"city": "武漢",
"description": "在武漢讀書,家在武漢!"
}
使用POST更新某個列的數(shù)據(jù)
POST /test_index/_update/1
{
"doc":{
"name":"think in java2",
"bir":"2021-06-03 10:34:00"
}
}
POST /test_index/_update/1
_update
是關(guān)鍵字,doc
也是關(guān)鍵字,如果doc
里的字段文檔里沒有,則會
在文檔里新增這個字段。
_update
方法不會刪除原有文檔,而是實現(xiàn)真正的數(shù)據(jù)更新。
使用GET命令查看:
#根據(jù)ID查詢
GET /test_index/_doc/1
2.10 刪除Document
# 刪除數(shù)據(jù)
DELETE /test_index/_doc/1
2.11 批量操作,添加、刪除、修改
支持在一次Api調(diào)用中,對不同的索引進行操作,支持index
、create
、update
、delete
。
操作中單條操作失敗,不會影響其它繼續(xù)操作,并且返回結(jié)果包括了每一條操作執(zhí)行的結(jié)果。
PUT /test_index/_doc/_bulk
{"index":{}}
{"name": "趙子龍1","age": 77,"city": "廣州","description": "趙子龍來自深圳寶安,但是在廣州工作!"}
{"index":{}}
{"name": "趙子龍2","age": 77,"city": "廣州","description": "趙子龍來自深圳寶安,但是在廣州工作!"}
{"delete":{"_id":"2"}}
{"delete":{"_id":"4"}}
{"update":{"_id":"5"}}
{"doc":{"name":"marry","age":20}}
index
:向索引中添加文檔,可以添加多個文檔;可以在新增的時候添加id:{"index":{"_id":"1"}}
delete
:刪除文檔,可以刪除多個文檔;
update
:修改文檔,可以修改多個文檔;
也可以進行create
操作:
{"create":{"_id":"3"}}
{"name":"kaka_create"}
這里需要大家注意:bulk api 對json語法有嚴格的要求,每個json串不能換行,只能放一行,同時一個json和另一
個json串之間必須有一個換行。
bulk api 可以同時操作多個索引,例如:
POST /_bulk
{"index":{"_index" : "test1","_id" : "1"}}
{"name":"kaka_bulk"}
{"delete":{"_index":"test1","_id":"2"}}
{"create":{"_index":"test2","_id":"3"}}
{"name":"kaka_create"}
{"update":{"_id":"1","_index":"test1"}}
{"doc":{"name":"kaka_bulk"}}
2.12 數(shù)據(jù)查詢
a、查詢所有數(shù)據(jù)
#查詢所有
GET /test_index/_search
b、根據(jù)ID查詢
#根據(jù)ID查詢
GET /test_index/_doc/3
c、Sort排序
#搜索排序
GET /test_index/_search
{
"query": {
"match_all": {}
},
"sort": {
"age": {
"order": "desc"
}
}
}
d、分頁
#分頁實現(xiàn)
GET /test_index/_search
{
"query": {
"match_all": {}
},
"sort": {
"age": {
"order": "desc"
}
},
"from": 0,
"size": 2
}
解釋:
from
:從下N的記錄開始查詢
size
:每頁顯示條數(shù)
2.13 批量讀取
GET /_mget
{
"docs": [
{"_index":"test_index","_id":"1"},
{"_index":"movies","_id":"2"}
]
}
2.14 批量搜索
POST /test_index/_msearch
{}
{"query":{"match_all":{}},"size":1}
{"index":"movies"}
{"query":{"match_all":{}},"size":1}
3、條件過濾
# 只搜索test_index索引下的內(nèi)容
GET /test_index/_search
# 搜索全部索引下的內(nèi)容
GET _search
3.1 term過濾
term主要用于分詞精確匹配,如字符串、數(shù)值、日期等
不適合情況:
1、列中除英文字符外有其它值
2、字符串值中有冒號或中文
3、系統(tǒng)自帶屬性如_version
如下案例:
#過濾查詢-term
GET /test_index/_search
{
"query": {
"term": {
"city": "武漢"
}
}
}
3.2 terms 過濾
terms
跟 term
有點類似,但 terms 允許指定多個匹配條件。 如果某個字段指定了多個值,那么文檔需要一起去
做匹配 。
#過濾查詢-terms 允許多個Term
GET /test_index/_search
{
"query": {
"terms": {
"city": ["武漢", "廣州"]
}
}
}
3.3 range 過濾
range
過濾允許我們按照指定范圍查找一批數(shù)據(jù),例如我們查詢年齡范圍。
#過濾-range 范圍過濾
#gt表示> gte表示=>
#lt表示< lte表示<=
GET /test_index/_search
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 57
}
}
}
}
3.4 exists過濾
exists
過濾可以用于查找擁有某個域的數(shù)據(jù)。
#過濾搜索 exists:是指包含某個域的數(shù)據(jù)檢索
GET /test_index/_search
{
"query": {
"exists": {
"field": "age"
}
}
}
3.5 bool 過濾
bool
過濾可以用來合并多個過濾條件查詢結(jié)果的布爾邏輯,它包含一下操作符:
-
must
: 多個查詢條件的完全匹配,相當于 and。 -
must_not
: 多個查詢條件的相反匹配,相當于 not。 -
should
: 至少有一個查詢條件匹配, 相當于 or。
這些參數(shù)可以分別繼承一個過濾條件或者一個過濾條件的數(shù)組。
#過濾搜索 bool
#must : 多個查詢條件的完全匹配,相當于 and。
#must_not : 多個查詢條件的相反匹配,相當于 not。
#should : 至少有一個查詢條件匹配, 相當于 or。
GET /test_index/_search
{
"query": {
"bool": {
"must": [{
"term": {
"city": {
"value": "深圳"
}
}
}, {
"range": {
"age": {
"gte": 20,
"lte": 99
}
}
}]
}
}
}
3.6 match_all 查詢
可以查詢到所有文檔,是沒有查詢條件下的默認語句。
#查詢所有 match_all
GET /test_index/_search
{
"query": {
"match_all": {}
}
}
3.7 match 查詢
match
查詢是一個標準查詢,不管你需要全文本查詢還是精確查詢基本上都要用到它。
如果你使用 match 查詢一個全文本字段,它會在真正查詢之前用分析器先分析match一下查詢字符。
#字符串匹配
GET /test_index/_search
{
"query": {
"match": {
"description": "武漢"
}
}
}
3.8 prefix 查詢
以什么字符開頭的,可以更簡單地用 prefix
,例如查詢所有以張開始的用戶描述。
#前綴匹配 prefix
GET /test_index/_search
{
"query": {
"prefix": {
"name": {
"value": "趙"
}
}
}
}
3.9 multi_match 查詢
multi_match
查詢允許你做match查詢的基礎(chǔ)上同時搜索多個字段,在多個字段中同時查一個。
#多個域匹配搜索
GET /test_index/_search
{
"query": {
"multi_match": {
"query": "深圳",
"fields": ["city", "description"]
}
}
}
4、使用Analyzer進行分詞
首先你得知道什么是分詞:Analysis把全文本轉(zhuǎn)換為一系列單詞的過程叫做分詞
Analysis通過Analyzer實現(xiàn)的,可以通過ElasticSearch內(nèi)置的分析器、或使用定制分析器
分詞器除了寫入時轉(zhuǎn)換此條,查詢query時也需要用相同的分析器對查詢語句進行分析
這里需要注意的是通過分詞轉(zhuǎn)化后把單詞的首字母變?yōu)樾?/p>
Analyzer的組成
Character Fiters
:針對原始文本處理,例如去除html
Tokenizer
:按照規(guī)則切分單詞
Token Filter
:將切分的單詞進行加工,轉(zhuǎn)為小寫,刪除stopwords并增加同義詞
ElasticSearch的內(nèi)置分詞器
# Standard Analyzer - 默認分詞器,按詞切分,小寫處理
# 只做單詞分割、并且把單詞轉(zhuǎn)為小寫
GET /_analyze
{
"analyzer":"standard",
"text":"If you don't expect quick success, you'll get a pawn every day"
}
# Simple Analyzer - 按照非字母切分(符號被過濾),小寫處理
# 按照非字母切分例如字母與字母之間的——,非字母的都被去除例如下邊的3
GET /_analyze
{
"analyzer" :"simple",
"text":"3 If you don't expect quick success, you'll get a pawn every day kaka-niuniu"
}
# Whitespace Analyzer - 按照空格切分,不轉(zhuǎn)小寫
# 僅僅是根據(jù)空格切分,再無其它
GET /_analyze
{
"analyzer":"whitespace",
"text":"3 If you don't expect quick success, you'll get a pawn every day"
}
# Stop Analyzer - 小寫處理,停用詞過濾(the,a, is)
# 按照非字母切分例如字母與字母之間的——,非字母的都被去除例如下邊的 2
# 相比Simple Analyze,會把the,a,is等修飾性詞語去除
GET /_analyze
{
"analyzer":"stop",
"text":"4 If you don't expect quick success, you'll get a pawn every day"
}
# Keyword Analyzer - 不分詞,直接將輸入當作輸出
# 不做任何分詞,直接把輸入的輸出,假如你不想使用任何分詞時就可以使用這個
GET /_analyze
{
"analyzer":"keyword",
"text":"5 If you don't expect quick success, you'll get a pawn every day"
}
# Patter Analyzer - 正則表達式,默認\W+(非字符分隔)
# 通過正則表達式進行分詞,默認是\W+,非字符的符號進行分割
GET /_analyze
{
"analyzer":"pattern",
"text":"6 If you don't expect quick success, you'll get a pawn every day"
}
# Language 一提供了30多種常見語言的分詞器
# 通過不同語言進行分詞
# 會把復(fù)數(shù)轉(zhuǎn)為單數(shù) ,會把單詞的ing去除
GET /_analyze
{
"analyzer":"english",
"text":"7 If you don't expect quick success, you'll get a pawn every day kakaing kakas"
}
# 中文分詞器
# 這個需要安裝分詞插件
GET /_analyze
{
"analyzer":"ik_max_word",
"text":"你好,我是咔咔"
}
5、Search Api
查詢語法:
GET /movies/_search?q=2012&df=title&sort=year:desc
q
:指定查詢語句內(nèi)容,使用Query String Syntax
df
:查詢字段,不指定時,會對所有字段進行查詢
sort
:排序、from和size用于分頁
profile
:可以查看查詢是如果被執(zhí)行的
5.1 指定字段查詢、泛查詢
指定字段查詢就是加上df
即可、泛查詢什么都不加。
例如指定字段查詢的是title中存在2012的數(shù)據(jù)
GET /movies/_search?q=title:2012
同樣也可以這樣來寫指定字段查詢
GET /movies/_search?q=2012&df=title
查看查詢是如果被執(zhí)行的:
GET /movies/_search?q=2012&df=title
{
"profile":true
}
5.2 分組與引號查詢
若你查詢值為Beautiful Mind
則等效于Beautiful OR Mind
,類似于MySQL中的or語句,意思為查詢的字段
中包含 Beautiful
或者 Mind
都會被查詢出來。
若你查詢值為"Beautiful Mind"
則等效于Beautiful AND Mind
,類似于MySQL中的and語句,意思為查詢
的字段中不僅要包含Beautiful 而且還需要包含 Mind ,跟MySQL中不同的是順序也不能變。
注意:這里你乍一眼看過去沒啥區(qū)別, 其實區(qū)別就在于有無引號
# 需要字段title中存在beautiful和mind,并且兩者的順序不能亂
GET /movies/_search?q=title:"Beautiful Mind"
{
"profile":"true"
}
# 需要字段title中出現(xiàn)beautiful 或 mind 都可以
GET /movies/_search?q=title:(Beautiful Mind)
{
"profile":"true"
}
5.3 布爾操作
可以使用AND / OR / NOT
或者 && / || / !
這里你會發(fā)現(xiàn)使用的都是大寫,+表示must(必須存在),-表
示not mast(必須不存在)。
# title 里邊必須有beautiful和mind
GET /movies/_search?q=title:(Beautiful AND Mind)
{
"profile":"true"
}
# title里邊包含beautiful必須沒有mind
GET /movies/_search?q=title:(Beautiful NOT Mind)
{
"profile":"true"
}
# title里包含beautiful或者mind
GET /movies/_search?q=title:(Beautiful OR Mind)
{
"profile":"true"
}
5.4 范圍查詢、通配符查詢、模糊匹配
# year年份大于1996的電影
GET /movies/_search?q=year:>1996
{
"profile":"true"
}
# title中存在b的數(shù)據(jù)
GET /movies/_search?q=title:b*
{
"profile":"true"
}
# 對于模糊匹配還是非常有必要的,因為會存在一起用戶會輸錯單詞,我們就可以給做近似度匹配
GET /movies/_search?q=title:beautifl~1
{
"profile":"true"
}
6、Request Body Search
在日常開發(fā)過程中,最經(jīng)常用的還是在Request Body中做。
6.1 正常查詢
sort
:需要排序的字段
_source
:查哪些字段
from
:頁數(shù)
size
:每頁數(shù)量
POST /movies/_search
{
"profile":"true",
"sort":[{"year":"desc"}],
"_source":["year"],
"from":0,
"size":2,
"query":{
"match_all": {}
}
}
6.2 腳本字段
POST /movies/_search
{
"script_fields":{
"new_field":{
"script":{
"lang":"painless",
"source":"doc['year'].value+'年'"
}
}
},
"query":{
"match_all": {}
}
}
這個案例就是把當前數(shù)據(jù)的year 拼上 “年” 組成的新字段然后返回,返回結(jié)果如下
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ThoWFOwK-1690463881683)(…/…/images/Elasticsearch/0263.png)]
從上面的結(jié)果可以看到只返回了腳本字段,沒有返回原始字段,那如何讓原始字段也跟著一起返回呢?
只需要在request body中加上_source
即可,當然也可以查詢指定字段"_source":["id","title"]
POST /movies/_search
{
"_source":"*",
"script_fields":{
"new_field":{
"script":{
"lang":"painless",
"source":"doc['year'].value+'年'"
}
}
},
"query":{
"match_all": {}
}
}
查看返回結(jié)果
6.3 查詢表達式Match
# title中包含sleepaway 或者 camp 即可
# 可以看到跟GET/movies/_search?q=title:(Beautiful Mind) 分組查詢返回結(jié)果是一致的
GET /movies/_search
{
"query":{
"match":{
"title":"Sleepaway Camp"
}
},
"profile":"true"
}
# title中必須包含sleepaway 和 camp 并且順序不能亂
# 可以看到跟GET /movies/_search?q=title:(Beautiful AND Mind)是一致的
GET /movies/_search
{
"query":{
"match":{
"title":{
"query":"Sleepaway Camp",
"operator":"AND"
}
}
},
"profile":"true"
}
# title 中查詢Sleepaway 和 Camp中間可以有一個任意值插入
# GET /movies/_search?q=title:beautifl~1
GET /movies/_doc/_search
{
"query":{
"match_phrase":{
"title":{
"query":"Sleepaway Camp",
"slop":1
}
}
},
"profile":"true"
}
7、 Query String 和 Simple Query String
# Query String 中可以使用and跟url 的query string一樣
# title 中必須存在sleepaway 和 camp 即可
# 跟url的 GET /movies/_search?q=title:(Beautiful Mind) 一致
POST /movies/_search
{
"query":{
"query_string":{
"default_field":"title",
"query":"Sleepaway AND Camp"
}
},
"profile":"true"
}
# simple_query_string 不支持and的使用,可以看到是把and當做一個詞來進行查詢
# title 中存在sleepaway 或 camp 即可
# "description" : "title:sleepaway title:and title:camp"
POST /movies/_search
{
"query":{
"simple_query_string": {
"query": "Sleepaway AND Camp",
"fields": ["title"]
}
},
"profile":"true"
}
# 如果想讓simple_query_string 執(zhí)行布爾操作,則需要給加上default_operator
# title中必須存在sleepaway 和 camp 即可
POST /movies/_search
{
"query":{
"simple_query_string": {
"query": "Sleepaway Camp",
"fields": ["title"],
"default_operator": "AND"
}
},
"profile":"true"
}
8、Mapping和常見字段類型
什么是Mapping
Mapping類似于數(shù)據(jù)庫中的schema,主要包括定義索引的字段名稱,定義字段的數(shù)據(jù)類型,配置倒排索引設(shè)置
什么是Dynamic Mapping
Mapping有一個屬性為dynamic,其定義了如何處理新增文檔中包含的新增字段,其有三個值可選默認為true
true
:一旦有新增字段的文檔寫入,Mapping也同時被更新
false
:Mapping不會被更新并且新增的字段也不會被索引,但是信息會出現(xiàn)在_source
中
strict
:文檔寫入失敗
常見類型
Json類型 | ElasticSearch類型 |
---|---|
字符串 | 日期格式為data、浮點數(shù)為float、整數(shù)為long、設(shè)置為text并且增加keyword子字段 |
布爾值 | boolean |
浮點數(shù) | float |
整數(shù) | long |
對象 | object |
數(shù)組 | 取第一個非空數(shù)值的類型所定 |
控制 | 忽略 |
PUT /kaka/_doc/1
{
"text":"kaka",
"int":10,
"boole_text":"false",
"boole":true,
"float_text":"1.234",
"float":1.234,
"loginData":"2005-11-24T22:20"
}
# 獲取索引kaka的mapping
GET /kaka/_mapping
8.1 自定義Mapping
設(shè)置字段不被索引
設(shè)置字段不被索引使用index,只需要給字段再加一個index:false
即可,同時注意一下mapping的設(shè)置格式
按照步驟走,你會得到一個這樣的錯誤Cannot search on field [mobile] since it is not
indexed
,意思就是不能搜索沒有索引的字段:
PUT /kaka
{
"mappings":{
"properties":{
"firstName":{
"type":"text"
},
"lastName":{
"type":"text"
},
"mobile":{
"type":"text",
"index":false
}
}
}
}
POST /kaka/_doc/1
{
"firstName":"kaka",
"lastName":"Niu",
"mobile":"123456"
}
GET /kaka/_search
{
"query":{
"match": {
"mobile":"123456"
}
}
}
設(shè)置copy_to
設(shè)置方式如下,copy_to
設(shè)置后再搜索時可以直接使用你定義的字段進行搜索:
PUT /kaka
{
"mappings":{
"properties":{
"firstName":{
"type":"text",
"copy_to":"allSearch"
},
"lastName":{
"type":"text",
"copy_to":"allSearch"
}
}
}
}
為了方便查看,這里咔咔再插入兩條數(shù)據(jù):
POST /kaka/_doc/1
{
"fitstName":"kaka",
"lastName":"niuniu"
}
POST /kaka/_doc/2
{
"fitstName":"kaka",
"lastName":"kaka niuniu"
}
進行查詢,返回的只有id為2的這條數(shù)據(jù),所以說使用copy_to后,代表著所有字段中都包含搜索的詞
POST /kaka/_search
{
"query":{
"match":{
"allSearch":"kaka"
}
},
"profile":"true"
}
9、自定義分詞器
分詞器是由Character Fiters
、Tokenizer
、Token Filter
組成的。
Character Filters
主要是對文本的替換、增加、刪除,可以配置多個Character Filters ,需要注意的是設(shè)置后
會影響Tokenizer的position、offset信息。
Character Filters
自帶的有 HTMl strip 去除html標簽、Mapping 字符串的替換、Pattern replace 正則匹配
替換Tokenizer 處理的就是分詞,內(nèi)置了非常多的分詞詳細可以在第二期文章中查看。
Token Filters
是將Tokenizer 分詞后的單詞進行增加、修改、刪除,例如進行轉(zhuǎn)為lowercase小寫字母、stop
去除修飾詞、synonym近義詞等。
9.1 自定義Character Filters
# Character Fiters之html的替換
# 會把text中的html標簽都會去除掉
POST /_analyze
{
"tokenizer":"keyword",
"char_filter":["html_strip"],
"text":"<span>咔咔閑談</span>"
}
# Character Fiters之替換值
# 會把text中的 i 替換為 kaka、hope 替換為 wish
POST /_analyze
{
"tokenizer":"keyword",
"char_filter":[
{
"type":"mapping",
"mappings":["i => kaka","hope => wish"]
}
],
"text":"I hope,if you don't expect quick success, you'll get a pawn every day."
}
# Character Fiters之正則表達式
# 使用正則表達式來獲取域名信息
POST /_analyze
{
"tokenizer":"keyword",
"char_filter":[
{
"type":"pattern_replace",
"pattern":"http://(.*)",
"replacement":"$1"
}
],
"text":"http://www.kakaxiantan.com"
}
9.2 自定義Token Filters
現(xiàn)在用的分詞器是whitespace
,這個分詞器是把詞使用空格隔開,但是現(xiàn)在還想讓詞變小寫并過濾修飾詞,應(yīng)
該怎么做呢?
POST /_analyze
{
"tokenizer":"whitespace",
"filter":["stop","lowercase"],
"text":"If on you don't expect quick success, you'll get a pawn every day"
}
9.3 實戰(zhàn)自定義分詞
本節(jié)開篇就知道analyze是通過Character Fiters、Tokenizer、Token Filter組成的,那么在自定義時這三個都是可
以自定義的,自定義分詞必存在analyzer、tokenizer、char_filter、filter。
這部分的定義都是需要在下面定義好規(guī)則,否則無法使用:
# 實戰(zhàn)自定義analyze
PUT /kaka
{
"settings":{
"analysis":{
"analyzer":{
"my_custom_analyzer":{
"type":"custom",
"char_filter":[
"emoticons"
],
"tokenizer":"punctuation",
"filter":[
"lowercase",
"englist_stop"
]
}
},
"tokenizer":{
"punctuation":{
"type":"keyword"
}
},
"char_filter":{
"emoticons":{
"type":"mapping",
"mappings":[
"123 => Kaka",
"456 => xian tan"
]
}
},
"filter":{
"englist_stop":{
"type":"stop",
"stopwords":"_english_"
}
}
}
}
}
# 執(zhí)行自定義的分詞
POST /kaka/_analyze
{
"analyzer":"my_custom_analyzer",
"text":" 123 456"
}
10、Index Template
在一個新索引新建并插入文檔后,會使用默認的setting、mapping
,如果你有設(shè)定settings、mappings
會覆蓋
默認的settings、mappings
配置。
# 創(chuàng)建索引并插入文檔
POST /kaka/_doc/1
{
"gongzhonghao":"123"
}
# 獲取settings、mappings
GET /kaka
接下來創(chuàng)建一個自己的模板:
# 設(shè)置一個只要是test開頭的索引都能使用的模板,在這個模板中我們將字符串中得數(shù)字也轉(zhuǎn)為了long類型,而非text
PUT /_template/kaka_tmp
{
"index_patterns":["test*"],
"order":1,
"settings":{
"number_of_shards":1,
"number_of_replicas":2
},
"mappings":{
# 讓時間不解析為date類型,返回是text類型
"date_detection":false,
# 讓雙引號下的數(shù)字解析為long類型,而非text類型
"numeric_detection":true
}
}
創(chuàng)建索引:
POST /test_kaka/_doc/1
{
"name":"123",
"date":"2022/01/13"
}
文章來源:http://www.zghlxwxcb.cn/news/detail-614078.html
GET /test_kaka
文章來源地址http://www.zghlxwxcb.cn/news/detail-614078.html
11、聚合查詢
GET /test_index/_search
{
"query": {
"match": {
"address": "Lane"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age"
}
},
"balanceAvg":{
"avg": {
"field": "age"
}
}
}
}
到了這里,關(guān)于Elasticsearch Query DSL的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!