緊接上次入門篇,這一篇主要記錄elasticsearch的結構化查詢 Query DSL.
結構化查詢是一種靈活的,多表現形式的查詢語言。 Elasticsearch在一個簡單的JSON接口中用結構化查詢來展現Lucene絕大多數能力。 你應當在你的產品中采用這種方式進行查詢。它使得你的查詢更加靈活,精准,易於閱讀並且易於debug。
single API
PUT /spider/ # 創建索引
POST /spider/ # 並不能用於創建索引,報錯
PUT /spider/movies/1/ # 插入document,索引為1,若數據存在,則為覆蓋更新
POST /spider/movies/ # 插入文檔,隨機生成索引
HEAD /spider/ # 用於驗證 索引或document是否存在,若存在則返回200狀態碼,不存在則返回404.
HEAD /spider/movies/1/
DELETE /spider/ # 刪除索引
DELETE /spider/movies/1/ # 刪除文檔
查詢與過濾
首先我們要明確查詢和過濾各自的優缺點,以及適用場景。
一條過濾語句會詢問每個文檔的字段值是否包含着特定值,查詢語句會詢問每個文檔的字段值與特定值的匹配程度如何。這一點較好區分,一條查詢語句會計算每個文檔與查詢語句的相關性,會給出一個相關性評分 _score,並且 按照相關性對匹配到的文檔進行排序。 這種評分方式非常適用於一個沒有完全配置結果的全文本搜索。
性能上的差異
使用過濾語句得到的結果集 -- 一個簡單的文檔列表,快速匹配運算並存入內存是十分方便的, 每個文檔僅需要1個字節。這些緩存的過濾結果集與后續請求的結合使用是非常高效的。
查詢語句不僅要查找相匹配的文檔,還需要計算每個文檔的相關性,所以一般來說查詢語句要比 過濾語句更耗時,並且查詢結果也不可緩存。
幸虧有了倒排索引,一個只匹配少量文檔的簡單查詢語句在百萬級文檔中的查詢效率會與一條經過緩存 的過濾語句旗鼓相當,甚至略占上風。 但是一般情況下,一條經過緩存的過濾查詢要遠勝一條查詢語句的執行效率。
過濾語句的目的就是縮小匹配的文檔結果集,所以需要仔細檢查過濾條件。
適用場景
原則上來說,使用查詢語句做全文本搜索或其他需要進行相關性評分的時候,剩下的全部用過濾語句
查詢、過濾語句
term過濾
term主要用於精確匹配哪些值,比如數字,日期,布爾值或 not_analyzed的字符串(未經分析的文本數據類型):
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
terms 過濾
terms 跟 term 有點類似,但 terms 允許指定多個匹配條件。 如果某個字段指定了多個值,那么文檔需要一起去做匹配:
{
"terms": {
"tag": [ "Java", "Python", "Php" ]
}
}
range過濾
range過濾允許我們按照指定范圍查找一批數據
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
exists 和 missing 過濾
exists 和 missing 過濾可以用於查找文檔中是否包含指定字段或沒有某個字段,類似於SQL語句中的IS_NULL條件
{
"exists": {
"field": "title"
}
}
bool 過濾
bool 過濾可以用來合並多個過濾條件查詢結果的布爾邏輯,它包含一下操作符:
- must :: 多個查詢條件的完全匹配,相當於 and。
- must_not :: 多個查詢條件的相反匹配,相當於 not。
- should :: 至少有一個查詢條件匹配, 相當於 or。
{
"bool": {
"must": { "term": { "folder": "inbox" }},
"must_not": { "term": { "tag": "spam" }},
"should": [
{ "term": { "starred": true }},
{ "term": { "unread": true }}
]
}
}
bool 查詢
bool 查詢與 bool 過濾相似,用於合並多個查詢子句。不同的是,bool 過濾可以直接給出是否匹配成功, 而bool 查詢要計算每一個查詢子句的 _score
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}
bool嵌套查詢
{
"bool" : {
"should" : [
{ "term" : {"productID" : "KDKE-B-9947-#kL5"}},
{ "bool" : {
"must" : [
{ "term" : {"productID" : "JODL-X-1937-#pV7"}},
{ "term" : {"price" : 30}}
]
}}
]
}
}
match_all 查詢
使用match_all 可以查詢到所有文檔,是沒有查詢條件下的默認語句。
{
"match_all": {}
}
match 查詢
match查詢是一個標准查詢,不管你需要全文本查詢還是精確查詢基本上都要用到它。
如果你使用 match 查詢一個全文本字段,它會在真正查詢之前用分析器先分析match一下查詢字符
{
"match": {
"tweet": "About Search"
}
}
multi_match 查詢
multi_match查詢允許你做match查詢的基礎上同時搜索多個字段
{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
match_phrase
短語查詢,full text search 是一個詞組,意味着三個詞的位置是連續且有順序
{
"match_phrase": {
"title": "full text search",
}
}
設置slop詞組間隔
{
"match_phrase": {
"title": {
"query": "full text search",
"slop":1
}
}
}
phrase_prefix 查詢
與詞組中最后一個詞條進行前綴匹配。
{
"query": {
"match_phrase_prefix": {
"title": {
"query": "秦時"
}
}
},
"from":0,
"size":5
}
regexp查詢
通配符查詢
{
"query": {
"regexp": {
"title": "W[0-9].+"
}
}
}
過濾查詢
查詢語句和過濾語句可以放在各自的上下文中,filtered已棄用,用bool代替
{
"query": {
"bool": {
"must": {"match": {"text": "quick brown fox"} },
"filter": {"term": {"status": "published"} }
}
}
"from":0, # 從0開始
"size":10, # 顯示條數
"sort":{"publish_date" :{"order":"desc"}}
}
返回指定字段
{
"_source":["id","name"],
"query":{...}
}