1. 程式人生 > >ES結構化查詢

ES結構化查詢

Elasticsearch結構化查詢

查詢準確值

term用於數字

term主要用在處理數字,布林值,日期和文字

GET /my_store/products/_search
{
    "query" : {
        "filtered" : { <1>
            "query" : {
                "match_all" : {} <2>
            },
            "filter" : {
                "term" : { <3>
                    "price"
: 20 } } } } }
  1. filtered 查詢同時接受 query 與 filter
  2. match_all 用來匹配所有文件,這是預設行為,所以在以後的例子中我們將省略掉 query 部分
  3. 這是我們上面見過的 term 過濾器,注意它在 filter 分句中的位置
term用於文字
內部過濾操作

組合過濾

布林過濾器

bool 過濾器由三部分組成:

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not
" : [], }
}

must:所有分句都必須匹配,跟AND相同
must_not:所有分句都必須不匹配,跟NOT相同
should:至少有一個分句匹配,與OR相同

SELECT product
FROM   products
WHERE  (price = 20 OR productID = "XHDK-A-1293-#fJ3")
  AND  (price != 30)
# 轉換成DSL
GET /my_store/products/_search
{
   "query" : {
      "filtered" : { <1>
         "filter" : {
            "bool"
: { "should" : [ { "term" : {"price" : 20}}, <2> { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} <2> ], "must_not" : { "term" : {"price" : 30} <3> } } } } } }
巢狀布林過濾器

雖然 bool 是一個組合過濾器而且接受子過濾器,需明白它自己仍然只是一個過濾器。這意味著你可以在 bool 過濾器中巢狀 bool 過濾器,讓你實現更復雜的布林邏輯

SELECT document
FROM   products
WHERE  productID      = "KDKE-B-9947-#kL5"
  OR (     productID = "JODL-X-1937-#pV7"
       AND price     = 30 )
# 轉化為DSL
GET /my_store/products/_search
{
   "query" : {
      "filtered" : {
         "filter" : {
            "bool" : {
              "should" : [
                { "term" : {"productID" : "KDKE-B-9947-#kL5"}}, <1>
                { "bool" : { <1>
                  "must" : [
                    { "term" : {"productID" : "JODL-X-1937-#pV7"}}, <2>
                    { "term" : {"price" : 30}} <2>
                  ]
                }}
              ]
           }
         }
      }
   }
}
查詢多個準確值

比起使用多個 term 過濾器,你可以用一個 terms 過濾器。terms 過濾器是 term 過濾器的複數版本

# 尋找 20 或 30 元的文件
GET /my_store/products/_search
{
    "query" : {
        "filtered" : {
            "filter" : {
                "terms" : { 
                    "price" : [20, 30]
                }
            }
        }
    }
}
term/terms:包含,而不是相等

term和terms都是包含操作,而不是相等操作

例項:過濾器{ “term” : { “tags” : “search” } }將匹配下面兩個文件:

{ "tags" : ["search"] }
{ "tags" : ["search", "open_source"] }

工作原理:
term過濾器檢查倒排索引中具有短語的文件,然後組成一個位元組集,在我們簡單例項中,我們有下面的倒排索引:

token docsIDs
open_source 2
search 1,2

當執行 term 過濾器來查詢 search 時,它直接在倒排索引中匹配值並找出相關的 ID。如你所見,文件 1 和文件 2 都包含 search,所以他們都作為結果集返回。
提示: 倒排索引的特性讓完全匹配一個欄位變得非常困難。你將如何確定一個文件只能包含你請求的短語?你將在索引中找出這個短語,解出所有相關文件 ID,然後掃描 索引中每一行來確定文件是否包含其他值。
由此可見,這將變得非常低效和開銷巨大。因此,term 和 terms 是 必須包含 操作,而不是 必須相等。

範圍

range 過濾器既能包含也能排除範圍,通過下面的選項:

  • gt: > 大於
  • lt: < 小於
  • gte: >= 大於或等於
  • lte: <= 小於或等於
SELECT document
FROM   products
WHERE  price BETWEEN 20 AND 40
# 轉化為DSL
GET /my_store/products/_search
{
    "query" : {
        "filtered" : {
            "filter" : {
                "range" : {
                    "price" : {
                        "gte" : 20,
                        "lt"  : 40
                    }
                }
            }
        }
    }
}
日期範圍
"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-07 00:00:00"
    }
}

當用於日期欄位時,range 過濾器支援日期數學操作。例如,我們想找到所有最近一個小時的文件:

"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

這個過濾器將始終能找出所有時間戳大於當前時間減 1 小時的文件,讓這個過濾器像移窗一樣通過你的文件。

日期計算也能用於實際的日期,而不是僅僅是一個像 now 一樣的佔位符。只要在日期後加上雙豎線 ||,就能使用日期數學表示式了。

# 早於 2014 年 1 月 1 號加一個月
"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" <1>
    }
}
字串範圍

range 過濾器也可以用於字串。字串範圍根據字典或字母順序來計算。例如,這些值按照字典順序排序:
* 5, 50, 6, B, C, a, ab, abb, abc, b

假如我們想讓範圍從 a 開始而不包含 b,我們可以用類似的 range 過濾器語法:

"range" : {
    "title" : {
        "gte" : "a",
        "lt" :  "b"
    }
}

當心基數:
數字和日期欄位的索引方式讓他們在計算範圍時十分高效。但對於字串來說卻不是這樣。為了在字串上執行範圍操作,Elasticsearch 會在這個範圍內的每個短語執行 term 操作。這比日期或數字的範圍操作慢得多。
字串範圍適用於一個基數較小的欄位,一個唯一短語個數較少的欄位。你的唯一短語數越多,搜尋就越慢。