因爲筆者在實際項目僅僅將ES用做索引數據庫,並無深刻研究過ES的搜索功能。並且鑑於筆者的搜索引擎知識有限,本文將僅僅介紹ES簡單(非全文)的查詢API。javascript
筆者本來打算在本文中介紹聚合API的內容,可是寫着寫着發現文章有點過長,不便於閱讀,故將聚合API的內容移至下一篇博客中。html
單單介紹理論和API是乏味和低效率的,本文將結合一個實際的例子來介紹這些API。下表是本文數據表的表結構,表名(type)爲「student」。注意,studentNo是本表的id,也就是_id字段的值與studentNo的值保持一致。java
字段名 | 字段含義 | 類型 | 是否能被索引 | 備註 |
---|---|---|---|---|
studentNo | 學號 | string | 是 | id |
name | 姓名 | string | 是 | |
sex | 性別 | string | 是 | |
age | 年齡 | integer | 是 | |
birthday | 出生年月 | date | 是 | |
address | 家庭住址 | string | 是 | |
classNo | 班級 | string | 是 | |
isLeader | 是否爲班幹部 | boolean | 是 |
上面的表結構所對應的mapping以下,將數據保存在索引名爲「student」的索引中。正則表達式
{
"student": { "properties": { "studentNo": { "type": "string", "index": "not_analyzed" }, "name": { "type": "string", "index": "not_analyzed" }, "male": { "type": "string", "index": "not_analyzed" }, "age": { "type": "integer" }, "birthday": { "type": "date", "format": "yyyy-MM-dd" }, "address": { "type": "string", "index": "not_analyzed" }, "classNo": { "type": "string", "index": "not_analyzed " }, "isLeader": { "type": "boolean" } } } }
索引中保存的數據以下,下面介紹的全部API都將基於這個數據表。sql
studentNo | name | male | age | birthday | classNo | address | isLeader |
---|---|---|---|---|---|---|---|
1 | 劉備 | 男 | 24 | 1985-02-03 | 1 | 湖南省長沙市 | true |
2 | 關羽 | 男 | 22 | 1987-08-23 | 2 | 四川省成都市 | false |
3 | 糜夫人 | 女 | 19 | 1990-06-12 | 1 | 上海市 | false |
4 | 張飛 | 男 | 20 | 1989-07-30 | 3 | 北京市 | false |
5 | 諸葛亮 | 男 | 18 | 1992-04-27 | 2 | 江蘇省南京市 | true |
6 | 孫尚香 | 女 | 16 | 1994-05-21 | 3 | false | |
7 | 馬超 | 男 | 19 | 1991-10-20 | 1 | 黑龍江省哈爾濱市 | false |
8 | 趙雲 | 男 | 23 | 1986-10-26 | 2 | 浙江省杭州市 | false |
ES中的查詢很是靈活,爲用戶提供了很是方便而強大的API。我的以爲ES的調用接口設計得很是好,全部接口合理且風格一致,值得好好研究!shell
ES爲用戶提供兩類查詢API,一類是在查詢階段就進行條件過濾的query查詢,另外一類是在query查詢出來的數據基礎上再進行過濾的filter查詢。這兩類查詢的區別是:數據庫
query和filter能夠單獨使用,也能夠相互嵌套使用,很是靈活。api
下面的狀況下適合使用query查詢:緩存
(1)Match All Querymarkdown
查詢全部的數據,至關於不帶條件查詢。下面的代碼是一個典型的match_all查詢的調用方式。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "match_all": {} } } '
查詢結果以下。其餘全部的查詢都是返回這種格式的數據。
{
"took": 156, // 查詢耗時(毫秒) "timed_out": false, // 是否超時 "_shards": { "total": 5, // 總共查詢的分片數 "successful": 5, // 查詢成功的分片數 "failed": 0 // 查詢失敗的分片數 }, "hits": { "total": 8, // 本次查詢的記錄數 "max_score": 1, // 查詢全部數據中的最大score "hits": [ // 數據列表 { "_index": "student", // 數據所屬的索引名 "_type": "student", // 數據所屬的type "_id": "4", // 數據的id值 "_score": 1, // 該記錄的score "_source": { // ES將原始數據保存到_source字段中 "studentNo": "4", "name": "張飛", "male": "男", "age": "20", "birthday": "1989-07-30", "classNo": "3", "isLeader": "F" } }, { …… // 其餘的數據格式相同,就不列出來了 } ] } }
查詢時,你會發現不管數據量有多大,每次最多隻能查到10條數據。這是由於ES服務端默認對查詢結果作了分頁處理,每頁默認的大小爲10。若是想本身指定查詢的數據,可以使用from和size字段,而且按指定的字段排序。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "match_all": {} }, "from": 2, // 從2條記錄開始取 "size": 4, // 取4條數據 "sort": { "studentNo": { // 按studentNo字段升序 "order": "asc"// 降序爲desc } } } '
注意:不要把from設得過大(超過10000),不然會致使ES服務端因頻繁GC而沒法正常提供服務。其實實際項目中也沒有誰會翻那麼多頁,可是爲了ES的可用性,務必要對分頁查詢的頁碼作必定的限制。
(2)term query
詞語查詢,若是是對未分詞的字段進行查詢,則表示精確查詢。查找名爲「諸葛亮」的學生,查詢結果爲學號爲5的記錄。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "term": { "name": "諸葛亮" } } } '
(3)Bool Query
Bool(布爾)查詢是一種複合型查詢,它能夠結合多個其餘的查詢條件。主要有3類邏輯查詢:
查找2班的班幹部,查詢結果爲學號爲5的記錄。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "bool": { "must": [ { "term": { "classNo": "2" } }, { "term": { "isLeader": "true" } } ] } } } '
(4)Ids Query
id字段查詢。查詢數據id值爲1和2的同窗,因爲id的值與studentNo相同,故查詢結果爲學號爲1和2的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "ids": { "type": "student", "values": [ "1", "2" ] } } } '
(5)Prefix Query
前綴查詢。查找姓【趙】的同窗,查詢結果是學號爲8的趙雲。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "prefix": { "name": "趙" } } } '
(6)Range Query
範圍查詢,針對date和number類型的數據。查找年齡到18~20歲的同窗,查詢結果是學號爲三、四、五、7的記錄。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "range": { "age": { "gte": "18", // 表示>= "lte": "20" // 表示<= } } } } '
實際上,對於date類型的數據,ES中以其時間戳(長整形)的形式存放的。
(7)Terms Query
多詞語查詢,查找符合詞語列表的數據。若是要查詢的字段索引爲not_analyzed類型,則terms查詢很是相似於關係型數據庫中的in查詢。下面查找學號爲1,3的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "terms": { "studentNo": [ "1", "3" ] } } } '
(8)Wildcard Query
通配符查詢,是簡化的正則表達式查詢,包括下面兩類通配符:
查找名字的最後一個字是「亮」的同窗,查詢結果是學號爲5的諸葛亮。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "wildcard": { "name": "*亮" } } } '
(9)Regexp Query同窗
正則表達式查詢,這是最靈活的字符串類型字段查詢方式。查找家住長沙市的學生,查詢結果爲學號爲1的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "query": { "regexp": { "address": ".*長沙市.*" // 這裏的.號表示任意一個字符 } } } '
下面的狀況下適合使用filter查詢:
filter和query的查詢方式有很多是重疊的,因此本節僅僅介紹API的調用,一些通用的注意的事項就再也不重複了。
(1)Term Filter
詞語查詢,若是是對未分詞的字段進行查詢,則表示精確查詢。查找名爲「諸葛亮」的學生,查詢結果爲學號爲5的記錄。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "term": { "name": "諸葛亮", "_cache" : true // 與query主要是這裏的區別,能夠設置數據緩存 } } } '
filter查詢方式均可以經過設置_cache爲true來緩存數據。若是下一次剛好以相同的查詢條件進行查詢而且該緩存沒有過時,就能夠直接從緩存中讀取數據,這樣就大大加快的查詢速度。
(2)Bool Filter
查找2班的班幹部,查詢結果爲學號爲5的記錄。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "bool": { "must": [ { "term": { "classNo": "2" } }, { "term": { "isLeader": "true" } } ] } } } '
(3)And Filter
And邏輯鏈接查詢,鏈接1個或1個以上查詢條件。它與bool查詢中的must查詢很是類似。實際上,and查詢能夠轉化爲對應的bool查詢。查找2班的班幹部,查詢結果爲學號爲5的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "and": [ { "term": { "classNo": "2" } }, { "term": { "isLeader": "true" } } ] } } '
(4)Or Filter
Or鏈接查詢,表示邏輯或。。查找2班或者是班幹部的學生名單,查詢結果爲學號爲一、二、五、8的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "or": [ { "term": { "classNo": "2" } }, { "term": { "isLeader": "true" } } ] } } '
(5)Exists Filter
存在查詢,查詢指定字段至少包含一個非null值的數據。若是字段索引爲not_analyzed類型,則查詢sql中的is not null查詢方式。查詢地址存在學生,查詢結果爲除了6以外的全部學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "exists": { "field": "address" } } } '
(6)Missing Filter
缺失值查詢,與Exists查詢正好相反。查詢地址不存在的學生,查詢結果爲學號爲6的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "missing": { "field": "address" } } } '
(7)Prefix Filter
前綴查詢。查找姓【趙】的同窗,查詢結果是學號爲8的趙雲。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "prefix": { "name": "趙" } } } '
(8)Range Filter
範圍查詢,針對date和number類型的數據。查找年齡到18~20歲的同窗,查詢結果是學號爲三、四、五、7的記錄。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "range": { "age": { "gte": "18", "lte": "20" } } } } '
(9)Terms Filter
多詞語查詢,查找符合詞語列表的數據。若是要查詢的字段索引爲not_analyzed類型,則terms查詢很是相似於關係型數據庫中的in查詢。下面查找學號爲1,3的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "terms": { "studentNo": [ "1", "3" ] } } } '
(10)Regexp Filter
正則表達式查詢,是最靈活的字符串類型字段查詢方式。查找家住長沙市的學生,查詢結果爲學號爲1的學生。
curl -XPOST "192.168.1.101:9200/student/student/_search" -d ' { "filter": { "regexp": { "address": ".*長沙市.*" } } } '