DSL語言高級查詢
DSL由葉子查詢子句和復合查詢子句兩種子句組成
無查詢條件:無查詢條件是查詢所有,默認是查詢所有的,或者使用match_all表示所有
GET /es_db/_doc/_search { "query":{ "match_all":{} } }
有查詢條件:
葉子條件查詢(單字段查詢條件) 3.1.1 模糊匹配 模糊匹配主要是針對文本類型的字段,文本類型的字段會對內容進行分詞,對查詢時,也會對搜索條件進行分詞,然后通過倒排索引查找到匹配的數據,模糊匹配主要通過match等參數來實現 match : 通過match關鍵詞模糊匹配條件內容 prefix : 前綴匹配 regexp : 通過正則表達式來匹配數據
match的復雜用法
match條件還支持以下參數:
query : 指定匹配的值
operator : 匹配條件類型
and : 條件分詞后都要匹配
or : 條件分詞后有一個匹配即可(默認)
minmum_should_match : 指定最小匹配的數量
3.1.2 精確匹配
term : 單個條件相等
terms : 單個字段屬於某個值數組內的值
range : 字段屬於某個范圍內的值
exists : 某個字段的值是否存在
ids : 通過ID批量查詢
組合條件查詢(多條件查詢)
組合條件查詢是將葉子條件查詢語句進行組合而形成的一個完整的查詢條件
bool : 各條件之間有and,or或not的關系
must : 各個條件都必須滿足,即各條件是and的關系
should : 各個條件有一個滿足即可,即各條件是or的關系
must_not : 不滿足所有條件,即各條件是not的關系
filter : 不計算相關度評分,它不計算_score即相關度評分,效率更高
constant_score : 不計算相關度評分
must/filter/shoud/must_not 等的子條件是通過 term/terms/range/ids/exists/match 等葉子條件為參數的
注:以上參數,當只有一個搜索條件時,must等對應的是一個對象,當是多個條件時,對應的是一個數組
連接查詢(多文檔合並查詢)
父子文檔查詢:parent/child
嵌套文檔查詢: nested
DSL查詢語言中存在兩種:查詢DSL(query DSL)和過濾DSL(filter DSL):區別
Query方式查詢:案例
根據名稱精確查詢姓名 term, term查詢不會對字段進行分詞查詢,會采用精確匹配
POST /es_db/_doc/_search { "query": { "term": { "name": "admin" } } }
類似:SQL: select * from student where name = 'admin'
注意: 采用term精確查詢, 查詢字段映射類型屬於為keyword
根據備注信息模糊查詢 match, match會根據該字段的分詞器,進行分詞查詢
POST /es_db/_doc/_search { "from": 0, "size": 2, "query": { "match": { "address": "廣州" } } } 類似:SQL: select * from user where address like '%廣州%' limit 0, 2
多字段模糊匹配查詢與精准查詢 multi_match
POST /es_db/_doc/_search { "query":{ "multi_match":{ "query":"張三", "fields":["address","name"] } } } 類似:SQL: select * from student where name like '%張三%' or address like '%張三%'
未指定字段條件查詢 query_string , 含 AND 與 OR 條件
POST /es_db/_doc/_search { "query":{ "query_string":{ "query":"廣州 OR 長沙" } } }
指定字段條件查詢 query_string , 含 AND 與 OR 條件
POST /es_db/_doc/_search { "query":{ "query_string":{ "query":"admin OR 長沙", "fields":["name","address"] } } }
范圍查詢
注:json請求字符串中部分字段的含義 range:范圍關鍵字 gte 大於等於 lte 小於等於 gt 大於 lt 小於 now 當前時間
POST /es_db/_doc/_search { "query" : { "range" : { "age" : { "gte":25, "lte":28 } } } } 類似:SQL: select * from user where age between 25 and 28
分頁、輸出字段、排序綜合查詢
POST /es_db/_doc/_search { "query" : { "range" : { "age" : { "gte":25, "lte":28 } } }, "from": 0, "size": 2, "_source": ["name", "age", "book"], "sort": {"age":"desc"} }
Filter過濾器方式查詢,它的查詢不會計算相關性分值,也不會對結果進行排序, 因此效率會高一點,查詢的結果可以被緩存
POST /es_db/_doc/_search { "query" : { "bool" : { "filter" : { "term":{ "age":25 } } } } }
總結:
1. match match:模糊匹配,需要指定字段名,但是輸入會進行分詞,比如"hello world"會進行拆分為hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的結果都會被查詢出來,也就是說match是一個部分匹配的模糊查詢。查詢條件相對來說比較寬松。 2. term term: 這種查詢和match在有些時候是等價的,比如我們查詢單個的詞hello,那么會和match查詢結果一樣,但是如果查詢"hello world",結果就相差很大,因為這個輸入不會進行分詞,就是說查詢的時候,是查詢字段分詞結果中是否有"hello world"的字樣,而不是查詢字段中包含"hello world"的字樣。當保存數據"hello world"時,elasticsearch會對字段內容進行分詞,"hello world"會被分成hello和world,不存在"hello world",因此這里的查詢結果會為空。這也是term查詢和match的區別。 3. match_phase match_phase:會對輸入做分詞,但是需要結果中也包含所有的分詞,而且順序要求一樣。以"hello world"為例,要求結果中必須包含hello和world,而且還要求他們是連着的,順序也是固定的,hello that world不滿足,world hello也不滿足條件。 4. query_string query_string:和match類似,但是match需要指定字段名,query_string是在所有字段中搜索,范圍更廣泛。
文檔映射
動態映射及規則:
在關系數據庫中,需要事先創建數據庫,然后在該數據庫下創建數據表,並創建表字段、類型、長度、主鍵等,最后才能基於表插入數據。而Elasticsearch中不需要定義Mapping映射(即關系型數據庫的表、字段等),在文檔
寫入Elasticsearch時,會根據文檔字段自動識別類型,這種機制稱之為動態映射。
動態映射實例:
2.1 刪除原創建的索引 DELETE /es_db 2.2 創建索引 PUT /es_db 2.3 創建文檔(ES根據數據類型, 會自動創建映射) PUT /es_db/_doc/1 { "name": "Jack", "sex": 1, "age": 25, "book": "java入門至精通", "address": "廣州小蠻腰" } 2.4 獲取文檔映射 GET /es_db/_mapping
靜態映射:
靜態映射是在Elasticsearch中也可以事先定義好映射,包含文檔的各字段類型、分詞器等,這種方式稱之為靜態映射。
3.1 刪除原創建的索引 DELETE /es_db 3.2 創建索引 PUT /es_db 3.3 設置文檔映射 PUT /es_db { "mappings":{ "properties":{ "name":{"type":"keyword","index":true,"store":true}, "sex":{"type":"integer","index":true,"store":true}, "age":{"type":"integer","index":true,"store":true}, "book":{"type":"text","index":true,"store":true}, "address":{"type":"text","index":true,"store":true} } } } 3.4 根據靜態映射創建文檔 PUT /es_db/_doc/1 { "name": "Jack", "sex": 1, "age": 25, "book": "elasticSearch入門至精通", "address": "廣州車陂" } 3.5 獲取文檔映射 GET /es_db/_mapping
核心類型(Core datatype)
字符串:string,string類型包含 text 和 keyword。 text:該類型被用來索引長文本,在創建索引前會將這些文本進行分詞,轉化為詞的組合,建立索引;允許es來檢索這些詞,text類型不能用來排序和聚合。 keyword:該類型不能分詞,可以被用來檢索過濾、排序和聚合,keyword類型不可用text進行分詞模糊檢索。 數值型:long、integer、short、byte、double、float 日期型:date 布爾型:boolean
keyword 與 text 映射類型的區別
將 book 字段設置為 keyword 映射 (只能精准查詢, 不能分詞查詢,能聚合、排序) POST /es_db/_doc/_search { "query": { "term": { "book": "elasticSearch入門至精通" } } }
將 book 字段設置為 text 映射能模糊查詢, 能分詞查詢,不能聚合、排序) POST /es_db/_doc/_search { "query": { "match": { "book": "elasticSearch入門至精通" } } }
創建靜態映射時指定text類型的ik分詞器
PUT /es_db { "mappings":{ "properties":{ "name":{"type":"keyword","index":true,"store":true}, "sex":{"type":"integer","index":true,"store":true}, "age":{"type":"integer","index":true,"store":true}, "book":{"type":"text","index":true,"store":true,"analyzer":"ik_smart","search_analyzer":"ik_smart"}, "address":{"type":"text","index":true,"store":true} } } }
Elasticsearch樂觀並發控制
在數據庫領域中,有兩種方法來確保並發更新,不會丟失數據: 1、悲觀並發控制 這種方法被關系型數據庫廣泛使用,它假定有變更沖突可能發生,因此阻塞訪問資源以防止沖突。 一個典型的例子是讀取一行數據之前先將其鎖住,確保只有放置鎖的線程能夠對這行數據進行修改。 2、樂觀並發控制 Elasticsearch 中使用的這種方法假定沖突是不可能發生的,並且不會阻塞正在嘗試的操作。 然而,如果源數據在讀寫當中被修改,更新將會失敗。應用程序接下來將決定該如何解決沖突。 例如,可以重試更新、使用新的數據
、或者將相關情況報告給用戶。
-- 再以創建一個文檔為例 ES老版本
PUT /db_index/_doc/1 { "name": "Jack", "sex": 1, "age": 25, "book": "Spring Boot 入門到精通", "remark": "hello world" }
-- 實現_version樂觀鎖更新文檔
PUT /db_index/_doc/1?version=1 { "name": "Jack", "sex": 1, "age": 25, "book": "Spring Boot 入門到精通", "remark": "hello world" }
ES新版本(7.x)不使用version進行並發版本控制 if_seq_no=版本值&if_primary_term=文檔位置
_seq_no:文檔版本號,作用同_version
_primary_term:文檔所在位置
POST /es_sc/_update/1/?if_seq_no=1&if_primary_term=1 { "doc": { "name": "圖靈學院1" } }