[ElasticSearch]Java API 之 詞條查詢(Term Level Query)


1. 詞條查詢(Term Query) 

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

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

  • /**
  • public static void termQuery(Client client, String index, String type) {
  • // Query
  • TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("country", "AWxhOn".toLowerCase());
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(termQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }

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

 

2. 多詞條查詢(Terms Query)

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

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

  • /**
  • public static void termsQuery(Client client, String index, String type) {
  • // Query
  • TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("country", "比利時", "德國");
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(termsQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }
輸出結果:
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 9 score 0.4898842 source {country=比利時, name=阿扎爾, club=切爾西俱樂部}
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 4 score 0.39103588 source {country=德國, name=穆勒, club=拜仁慕尼黑俱樂部}
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 1 score 0.25427115 source {country=比利時, name=德布勞內, club=曼城俱樂部}

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


3. 范圍查詢(Range Query)

 

范圍查詢使我們能夠找到在某一字段值在某個范圍里的文檔,字段可以是數值型,也可以是基於字符串的。范圍查詢只能針對單個字段。

方法:

 

 

(1)gte() :范圍查詢將匹配字段值大於或等於此參數值的文檔。

(2)gt() :范圍查詢將匹配字段值大於此參數值的文檔。

(3)lte() :范圍查詢將匹配字段值小於或等於此參數值的文檔。

(4)lt() :范圍查詢將匹配字段值小於此參數值的文檔。

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

includeLower(true) 表示 from() 查詢將匹配字段值大於或等於此參數值的文檔;

includeLower(false) 表示 from() 查詢將匹配字段值大於此參數值的文檔;

includeUpper(true) 表示 to() 查詢將匹配字段值小於或等於此參數值的文檔;

includeUpper(false) 表示 to() 查詢將匹配字段值小於此參數值的文檔;

  • /**
  • public static void rangeQuery(Client client, String index, String type) {
  • // Query
  • RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
  • .from(19);
  • .to(21);
  • .includeLower(true);
  • .includeUpper(true);
  • //RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(19).lte(21);
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(rangeQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
  • // 結果
  • (searchResponse);
  • }

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

  • QueryBuilder queryBuilder = QueryBuilders.rangeQuery("age").gte(19).lte(21);

輸出結果:

  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 9 score 1.0 source {college=計算機學院, school=麻省理工大學, sex=boy, name=廖力生, age=21}
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 2 score 1.0 source {college=通信學院, school=西安電子科技大學, sex=boy, name=李源一, age=19}
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 4 score 1.0 source {college=電子工程學院, school=中國科技大學, sex=girl, name=王俊輝, age=21}
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 1 score 1.0 source {college=計算機學院, school=西安電子科技大學, sex=boy, name=徐欣, age=21}
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 11 score 1.0 source {college=計算機學院ddddd, school=中國科技大學, sex=girl, name=王俊輝2, age=21}

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


4. 存在查詢(Exists Query)

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

  • /**
  • public static void existsQuery(Client client, String index, String type) {
  • // Query
  • ExistsQueryBuilder existsQueryBuilder = QueryBuilders.existsQuery("name");
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(existsQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }

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

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

     

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

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

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

    下面幾個文檔不會得到上面代碼的匹配:

     
  • "bar" }
  •  

    第一個是null值。

    第二個沒有值。

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

    第四個與指定字段不匹配。

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


    5. 前綴查詢(Prefix Query)

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

     
  • /**
  • public static void prefixQuery(Client client, String index, String type) {
  • // Query
  • PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery("country", "葡萄");
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(prefixQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }
  •  

    輸出結果:

     
  • .sjf.open.api.QueryAPI - ---------- QueryAPI id 3 score 1.0 source {country=葡萄牙, name=C羅, club=皇家馬德里俱樂部}
  •  

    備注:

    進行下面前綴查詢,沒有查找到相應信息,但是數據源中是有的:

     
  • 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)

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

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

  • /**
  • public static void wildcardQuery(Client client, String index, String type){
  • // Query
  • WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("country", "西*牙");
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(wildcardQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }
  •  

    輸出結果:

     
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 8 score 1.0 source {country=西班牙, name=托雷斯, club=馬德里競技俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 6 score 1.0 source {country=西班牙, name=布斯克茨, club=巴薩羅那俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 7 score 1.0 source {country=西班牙, name=哈維, club=巴薩羅那俱樂部}
  •  

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


    7. 正則表達式查詢(Regexp Query)

    正則表達式查詢允許我們獲取指定字段滿足正則表達式的文檔,和前綴查詢一樣,正則表達式查詢指定字段是未分析的(not analyzed)。正則表達式查詢的性能取決於所選的正則表達式。如果我們的正則表達式匹配許多詞條,查詢將很慢。一般規則是,正則表達式匹配的詞條數越高,查詢越慢。

     
  • /**
  • public static void regexpQuery(Client client, String index, String type){
  • // Query
  • RegexpQueryBuilder regexpQueryBuilder = QueryBuilders.regexpQuery("country", "(西班|葡萄)牙");
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(regexpQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }
  •  

    輸出結果:

     
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 8 score 1.0 source {country=西班牙, name=托雷斯, club=馬德里競技俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 6 score 1.0 source {country=西班牙, name=布斯克茨, club=巴薩羅那俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 7 score 1.0 source {country=西班牙, name=哈維, club=巴薩羅那俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 3 score 1.0 source {country=葡萄牙, name=C羅, club=皇家馬德里俱樂部}
  •  

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


    8. 模糊查詢(Fuzzy Query)

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

    8.1 string類型字段

    模糊查詢生成所有可能跟指定詞條的匹配結果(在fuzziness指定的最大編輯距離范圍之內)。然后檢查生成的所有結果是否是在索引中。

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

     

  • /**
  • public static void fuzzyQuery(Client client, String index, String type){
  • // Query
  • FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("country", "洗班牙");
  • // 最大編輯距離
  • .fuzziness(Fuzziness.ONE);
  • // 公共前綴
  • .prefixLength(0);
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(fuzzyQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }
  •  

    輸出結果:

     
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 8 score 1.6931472 source {country=西班牙, name=托雷斯, club=馬德里競技俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 6 score 1.4054651 source {country=西班牙, name=布斯克茨, club=巴薩羅那俱樂部}
  • .sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 7 score 1.0 source {country=西班牙, name=哈維, club=巴薩羅那俱樂部}
  •  
    8.2 數字和日期類型字段

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

     

     
  • field value <= +fuzziness
  •  

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

     
  • /**
  • public static void fuzzyQuery2(Client client, String index, String type){
  • // Query
  • FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("age", "18");
  • .fuzziness(Fuzziness.TWO);
  • // Search
  • SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  • .setTypes(type);
  • .setQuery(fuzzyQueryBuilder);
  • // 執行
  • SearchResponse searchResponse = searchRequestBuilder.get();
  • // 結果
  • (searchResponse);
  • }
  •   

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


    9. 說明

    本代碼基於ElasticSearch 2.4.1 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM