天天看點

java實作查詢功能6,Java操作Elasticsearch6實作基本查詢

Java操作Elasticsearch6實作基本查詢

Java操作Elasticsearch6實作基本查詢

引言

業務系統接入Elasticsearch搜尋服務後,開始了寫查詢接口的任務,本篇部落格将總結Java操作Elasticsearch一些基本查詢的實作。

基礎代碼

建構查詢條件,對應Elasticsearch其實就是建構SearchRequest對象,指定索引庫Name,指定索引庫Type,建立SearchSourceBuilder對象,根據需求建立QueryBuilder對象,下面是建立和使用建構對象的基礎代碼:

SearchRequest searchRequest = new SearchRequest();

searchRequest.indices("indexName");

searchRequest.types("indexType");

SearchSourceBuilder builder = new SearchSourceBuilder();

BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

builder.query(boolQueryBuilder);

searchRequest.source(builder);

構造查詢條件代碼

1. termQuery:精确查詢(不分詞)

//termQuery 精确比對,參數(Es中對應字段的keyword,比對的值)

boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName.keyword", dto.getGradeName()));

使用termQuery要注意的是,Elasticsearch5之後,取消了string類型,将原來的string類型拆分為text和keyword兩種類型,他們的差別在于text會對字段進行分詞處理,而keyword則不會。下面通過例子來看一下兩者的差別:

使用’gradeName.keyword’字段查詢,查詢條件“六年級”,查詢結果如下:

java實作查詢功能6,Java操作Elasticsearch6實作基本查詢

如果在Elasticsearch5之後,查詢條件年級傳入"六年級",使用’gradeName’字段查詢,是查詢不到結果的:

//termQuery 精确比對,參數(Es中的字段key,比對的值)

boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", dto.getGradeName()));

java實作查詢功能6,Java操作Elasticsearch6實作基本查詢

原因是在查詢中,如果使用’gradeName’查詢,是将gradeName作為text類型查詢,而使用’gradeName.keyword’,則是将其作為keyword類型查詢,前者會對查詢内容做分詞處理之後再比對,而後者則是直接精确比對。

當我們沒有對索引字段預先指定mapping,Elasticsearch會進行動态映射,如傳入價格字段的值為12,會映射為long類型;對傳入ip字段的值為’192.168.0.12’,會映射為ip類型。對于普通字元串,elasticsearch将其映射為text類型,為了保證對這些字段做精确查詢和聚合的能力,又同時做了keyword類型的映射,作為該字段的fields屬性寫到_mapping中。

Elasticsearch的termQuery做的是精确查詢而不是分詞查詢,是以對text類型的字段做term查詢則是查不到結果的(除非字段本身經過分詞器處理後不變,未被轉換或分詞)。此時,必須使用gradeName.keyword來對gradeName字段以keyword類型進行精确比對。

2. matchQuery:比對查詢(分詞)

boolQueryBuilder.filter(QueryBuilders.matchQuery("gradeName", dto.getGradeName()));

match query搜尋的時候,首先會解析查詢字元串,進行分詞,然後查詢,是以假如我搜尋的條件輸入的是"六年級",則會把各個年級(一年級至九年級)的資料都查詢出來,因為其中都包含’年級’,結果如下:

java實作查詢功能6,Java操作Elasticsearch6實作基本查詢

而上面提到的term query,輸入的查詢内容是什麼,就會按照什麼去查詢,并不會解析查詢内容,對它分詞。

3. queryString:精确查詢

QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(dto.getGradeName()).field("gradeName").defaultOperator(Operator.AND);

boolQueryBuilder.must(queryStringQueryBuilder);

這裡使用QueryStringQueryBuilder構造查詢條件,并沒有用keyword類型字段’gradeName.keyword’,也可以查詢到結果,并且使用defaultOperator拼接操作條件AND或者OR即可。

4. wildcardQuery:模糊查詢

//wildcardQuery 模糊比對,參數(Es中的字段key,比對的值)

boolQueryBuilder.filter(QueryBuilders.wildcardQuery("phone", String.format("*%s*", dto.getPhone())));

5. rangeQuery:範圍查詢

//範圍查詢(國小階段:大于等于1,小于等于6)

boolQueryBuilder.filter(QueryBuilders.rangeQuery("gradeCode").from(1, true).to(6, true));

from和to的第二個參數表明是否包含上限值或下限值。

6. Condition 1 OR Condition 2 的實作

BoolQueryBuilder fuzzyQueryBuilder = new BoolQueryBuilder();

fuzzyQueryBuilder.should(QueryBuilders.wildcardQuery("nickName", String.format("*%s*", dto.getFuzzyCondition())))

.should(QueryBuilders.wildcardQuery("phone", String.format("*%s*", dto.getFuzzyCondition())))

這裡的should相當于OR,多個字段之間用should拼接,可實作多個字段模糊查詢。

7. (Condition 1 OR Condition 2) AND Condition3 的實作

//構造條件3使用

BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

//構造條件1和條件2使用

BoolQueryBuilder fuzzyQueryBuilder = new BoolQueryBuilder();

//手機号或昵稱

if (StringUtils.isNotBlank(dto.getFuzzyCondition())) {

//must相當于and,拼接條件,should相當于or,多個字段模糊查詢條件拼接

boolQueryBuilder.must(fuzzyQueryBuilder.should(QueryBuilders.wildcardQuery("nickName", String.format("*%s*", dto.getFuzzyCondition())))

.should(QueryBuilders.wildcardQuery("phone", String.format("*%s*", dto.getFuzzyCondition()))));

}

//學員類型:付費/未付費

if (dto.getType() != null) {

boolQueryBuilder.filter(QueryBuilders.termQuery("type", dto.getType()));

}

這裡我們需要建構兩個QueryBuilder,在QueryBuilder之間,使用must進行拼接,相當于AND條件。

總結

以上總結的都屬于一些基本的查詢,能滿足目前業務系統的需求,以後遇到進階查詢再單獨進行總結。

Java操作Elasticsearch6實作基本查詢相關教程