天天看點

[ElasticSearch]Java API之TermQuery

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/SunnyYoona/article/details/52852483

1. 詞條查詢(Term Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#1-term-query

詞條查詢是ElasticSearch的一個簡單查詢。它僅比對在給定字段中含有該詞條的文檔,而且是确切的、未經分析的詞條。term 查詢 會查找我們設定的準确值。term 查詢本身很簡單,它接受一個字段名和我們希望查找的值。

下面代碼查詢将比對 college 字段中含有"California"一詞的文檔。記住,詞條查詢是未經分析的,是以需要提供跟索引文檔中的詞條完全比對的詞條。請注意,我們使用小寫開頭的california來搜尋,而不是California,因為California一詞在建立索引時已經變成了california(預設分詞器)。

// Query
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("country", "AWxhOn".toLowerCase());
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(termQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           

參考:

https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-term-query.html

2. 多詞條查詢(Terms Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#2-terms-query

詞條查詢(Term Query)允許比對單個未經分析的詞條,多詞條查詢(Terms Query)可以用來比對多個這樣的詞條。隻要指定字段包含任一我們給定的詞條,就可以查詢到該文檔。

下面代碼得到所有在 country 字段中含有 “德國” 或 "比利時" 的文檔。

// Query
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("country", "比利時", "德國");
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(termsQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-terms-query.html

3. 範圍查詢(Range Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#3-range-query

範圍查詢使我們能夠找到在某一字段值在某個範圍裡的文檔,字段可以是數值型,也可以是基于字元串的。範圍查詢隻能針對單個字段。

方法: (1) gte() :範圍查詢将比對字段值大于或等于此參數值的文檔。

(2) gt() :範圍查詢将比對字段值大于此參數值的文檔。

(3) lte() :範圍查詢将比對字段值小于或等于此參數值的文檔。

(4) lt() :範圍查詢将比對字段值小于此參數值的文檔。

(5) from() 開始值 to() 結束值 這兩個函數與includeLower()和includeUpper()函數配套使用。

(6) includeLower(true) 表示 from() 查詢将比對字段值大于或等于此參數值的文檔。

(7) includeLower(false) 表示 from() 查詢将比對字段值大于此參數值的文檔。

(8) includeUpper(true) 表示 to() 查詢将比對字段值小于或等于此參數值的文檔。

(9) includeUpper(false) 表示 to() 查詢将比對字段值小于此參數值的文檔。

// Query
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
rangeQueryBuilder.from(19);
rangeQueryBuilder.to(21);
rangeQueryBuilder.includeLower(true);
rangeQueryBuilder.includeUpper(true);
//RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(19).lte(21);
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(rangeQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
           

上面代碼中的查詢語句與下面的是等價的:

QueryBuilder queryBuilder = QueryBuilders.rangeQuery("age").gte(19).lte(21);
           
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-range-query.html

4. 存在查詢(Exists Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#4-exists-query

如果指定字段上至少存在一個no-null的值就會傳回該文檔。

// Query
ExistsQueryBuilder existsQueryBuilder = QueryBuilders.existsQuery("name");
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(existsQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           

舉例說明,下面的幾個文檔都會得到上面代碼的比對:

{ "name": "yoona" }
{ "name": "" }
{ "name": "-" }
{ "name": ["yoona"] }
{ "name": ["yoona", null ] }
           

第一個是字元串,是一個非null的值。

第二個是空字元串,也是非null。

第三個使用标準分析器的情況下盡管不會傳回詞條,但是原始字段值是非null的(Even though the standard analyzer would emit zero tokens, the original field is non-null)。

第五個中至少有一個是非null值。

下面幾個文檔不會得到上面代碼的比對:

{ "name": null }
{ "name": [] }
{ "name": [null] }
{ "user":  "bar" }
           

第一個是null值。

第二個沒有值。

第三個隻有null值,至少需要一個非null值。

第四個與指定字段不比對。

https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-exists-query.html

5. 字首查詢(Prefix Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#5-prefix-query

字首查詢讓我們比對這樣的文檔:它們的特定字段已給定的字首開始。下面代碼中我們查詢所有country字段以"葡萄"開始的文檔。

// Query
PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery("country", "葡萄");

// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(prefixQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           

備注:

進行下面字首查詢,沒有查找到相應資訊,但是資料源中是有的:
QueryBuilder queryBuilder = QueryBuilders.prefixQuery("club", "皇家馬德裡");
           

産生以上差别的主要原因是club字段(預設mapping配置)進行了分析器分析了,索引中的資料已經不在是"皇家馬德裡",而country字段沒有進行分析(mapping配置not_analyzed)。

https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-prefix-query.html

6. 通配符查詢(Wildcard Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#6-wildcard-query

通配符查詢允許我們擷取指定字段滿足通配符表達式的文檔,和字首查詢一樣,通配符查詢指定字段是未分析的(not analyzed)。

可以使用星号代替0個或多個字元,使用問号代替一個字元。星号表示比對的數量不受限制,而後者的比對字元數則受到限制。這個技巧主要用于英文搜尋中,如輸入““computer*”,就可以找到“computer、computers、computerised、computerized”等單詞,而輸入“comp?ter”,則隻能找到“computer、compater、competer”等單詞。注意的是通配符查詢不太注重性能,在可能時盡量避免,特别是要避免字首通配符(以以通配符開始的詞條)。

// Query
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("country", "西*牙");
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(wildcardQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-wildcard-query.html

7. 正規表達式查詢(Regexp Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#7-regexp-query

正規表達式查詢允許我們擷取指定字段滿足正規表達式的文檔,和字首查詢一樣,正規表達式查詢指定字段是未分析的(not analyzed)。正規表達式查詢的性能取決于所選的正規表達式。如果我們的正規表達式比對許多詞條,查詢将很慢。一般規則是,正規表達式比對的詞條數越高,查詢越慢。

// Query
RegexpQueryBuilder regexpQueryBuilder = QueryBuilders.regexpQuery("country", "(西班|葡萄)牙");

// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(regexpQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-regexp-query.html

8. 模糊查詢(Fuzzy Query) http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#8-fuzzy-query

如果指定的字段是string類型,模糊查詢是基于編輯距離算法來比對文檔。編輯距離的計算基于我們提供的查詢詞條和被搜尋文檔。如果指定的字段是數值類型或者日期類型,模糊查詢基于在字段值上進行加減操作來比對文檔(The fuzzy query uses similarity based on Levenshtein edit distance for string fields, and a +/-margin on numeric and date fields)。此查詢很占用CPU資源,但當需要模糊比對時它很有用,例如,當使用者拼寫錯誤時。另外我們可以在搜尋詞的尾部加上字元 “~” 來進行模糊查詢。

8.1 string類型字段 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#8-1-string

模糊查詢生成所有可能跟指定詞條的比對結果(在fuzziness指定的最大編輯距離範圍之内)。然後檢查生成的所有結果是否是在索引中。

下面代碼中模糊查詢country字段為”西班牙“的所有文檔,同時指定最大編輯距離為1(fuzziness),最少公共字首為0(prefixLength),即不需要公共字首。

// Query
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("country", "洗班牙");
// 最大編輯距離
fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
// 公共字首
fuzzyQueryBuilder.prefixLength(0);
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(fuzzyQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           
8.2 數字和日期類型字段 http://gitlab.corp.qunar.com/jifeng.si/learningnotes/blob/master/IT/%E5%A4%A7%E6%95%B0%E6%8D%AE/ElasticSearch/%5BElasticSearch%5DJava%20API%E4%B9%8BTermQuery.md#8-2

與範圍查詢(Range Query)的around比較類似。形成在指定值上上下波動fuzziness大小的一個範圍:

-fuzziness <= field value <= +fuzziness
           

下面代碼在18歲上下波動2歲,形成[17-19]的一個範圍查詢:

// Query
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("age", "18");
fuzzyQueryBuilder.fuzziness(Fuzziness.TWO);
// Search
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
searchRequestBuilder.setTypes(type);
searchRequestBuilder.setQuery(fuzzyQueryBuilder);
// 執行
SearchResponse searchResponse = searchRequestBuilder.get();
           
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-fuzzy-query.html

備注:

本代碼基于ElasticSearch 2.4.1