本文继续上文(Elasticsearch 入门实战(5)--Java API Client 使用一(Index,Document,Ingest,SQL APIs))介绍 Java API Client,相关的环境及软件信息如下:CentOS 7.6.1810、Java 1.8.0_341(客户端用)、Elasticsearch 8.13.4、elasticsearch-java 8.13.4。
1、Search APIs
1.1、Count API(查询文档数量)
/**
* 查询文档数量
*/
@Test
public void count() throws IOException {
//查询该索引的所有文档数量
CountResponse response = client.count(builder -> builder.index(INDEX_NAME));
log.info("response={}", response);
//通过 Lucene 查询语法指定条件;8.13.4会报错”contains unrecognized parameter: [q]“,因为 API 提交了请求 "{}",应该时不需要请求体
//response = client.count(builder -> builder.index(INDEX_NAME).q("name:杜甫"));
log.info("response={}", response);
//通过 "Query DSL" 指定条件
response = client.count(builder -> builder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.term(termQueryBuilder -> termQueryBuilder
.field("name").value("杜甫")
)
)
);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
1.2、Search API(查询文档)
1.2.1、query
1.2.1.1、term/terms 查询
/**
* term/terms 查询,对输入内容不做分词处理
*/
@Test
public void searchTerm() throws IOException {
SearchResponse<Map> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.term(termQueryBuilder -> termQueryBuilder
.field("name").value("李白")))
.sort(sortOptionsBuilder -> sortOptionsBuilder
.field(fieldSortBuilder -> fieldSortBuilder
.field("age").order(SortOrder.Asc)))
.source(sourceConfigBuilder -> sourceConfigBuilder
.filter(sourceFilterBuilder -> sourceFilterBuilder
.includes("age", "name")))
.from(0)
.size(10)
, Map.class);
log.info("response={}", response);
List<FieldValue> words = new ArrayList<>();
words.add(new FieldValue.Builder().stringValue("李白").build());
words.add(new FieldValue.Builder().stringValue("杜甫").build());
SearchResponse<Poet> response2 = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.terms(termsQueryBuilder -> termsQueryBuilder
.field("name").terms(termsQueryFieldBuilder -> termsQueryFieldBuilder.value(words))))
.source(sourceConfigBuilder -> sourceConfigBuilder
.filter(sourceFilterBuilder -> sourceFilterBuilder
.excludes("about")))
.from(0)
.size(10)
, Poet.class);
log.info("response2={}", response2);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
1.2.1.2、range 查询
/**
* range 查询,范围查询
*/
@Test
public void searchRange() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.range(rangeQueryBuilder -> rangeQueryBuilder
.field("age").gte(JsonData.of("20")).lt(JsonData.of("40"))))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
1.2.1.3、exists 查询
/**
* exists 查询,查询对应字段不为空的数据
*/
@Test
public void exists() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME).query(builder -> builder.exists(builder1 -> builder1.field("poems")))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
1.2.1.4、match 相关查询
A、match
/**
* match查询,对输入内容先分词再查询
*/
@Test
public void searchMatch() throws IOException {
SearchResponse<Map> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想")))
, Map.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
B、multi_match
/**
* multi_match 查询,多个字段进行匹配。
*/
@Test
public void searchMultiMatch() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder
.fields("about", "success").query("思想")))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
C、match_phrase
/**
* match_phrase 查询,类似 match,先把查询字符串分词生成一个词列表,查询包含所有这些词且这些词在文档中出现次序一致的数据。
*/
@Test
public void searchMatchPhrase() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.matchPhrase(matchPhraseQueryBuilder -> matchPhraseQueryBuilder
.field("success").query("伟大作家")))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
D、match_all
/**
* match_all 查询,查询所有文档
*/
@Test
public void searchMatchAll() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.matchAll(matchAllQueryBuilder -> matchAllQueryBuilder))
, Poet.class);
log.info("response={}", response);
//不加请求体,也是一样的效果,查询所有文档。
response = client.search(searchRequestBuilder -> searchRequestBuilder.index(INDEX_NAME), Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
E、match_none
/**
* match_none 查询,与 match_all 相反,返回 0 个文档。
*/
@Test
public void searchMatchNone() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.matchNone(matchAllQueryBuilder -> matchAllQueryBuilder))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
1.2.1.5、query_string 查询
/**
* query_string 查询,可以同时实现多种查询
*/
@Test
public void searchQueryString() throws IOException {
//类似 match
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.defaultField("success").query("古典文学")))
, Poet.class);
log.info("response={}", response);
//类似 mulit_match
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("about", "success").query("古典文学")))
, Poet.class);
log.info("response={}", response);
//类似 match_phrase
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.defaultField("success").query("\"文学作家\"")))
, Poet.class);
log.info(response.toString());
//带运算符查询,运算符两边的词不再分词
//查询同时包含 ”文学“ 和 ”伟大“ 的文档
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("success").query("文学 AND 伟大")))
, Poet.class);
log.info("response={}", response);
//等同上一个查询
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("success").query("文学 伟大").defaultOperator(Operator.And)))
, Poet.class);
log.info("response={}", response);
//查询 name 或 success 字段包含"文学"和"伟大"这两个单词,或者包含"李白"这个单词的文档。
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("name","success").query("(文学 AND 伟大) OR 高度")))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
1.2.1.6、simple_query_string 查询
/**
* simple_query_string 查询,类似 query_string,主要区别如下:
* 1、不支持 AND OR NOT,会当做字符处理;使用 + 代替 AND,| 代替 OR,- 代替 NOT
* 2、会忽略错误的语法
*/
@Test
public void searchSimpleQueryString() throws IOException {
//查询同时包含 ”文学“ 和 ”伟大“ 的文档
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.simpleQueryString(simpleQueryStringQueryBuilder -> simpleQueryStringQueryBuilder
.fields("success").query("文学 + 伟大")))
, Poet.class);
log.info("response={}", response);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
3.4.7、fuzzy 查询
/**
* 模糊查询
*/
@Test
public void searchFuzzy() throws IOException {
//全文查询时使用模糊参数,先分词再计算模糊选项。
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思考").fuzziness("1")))
, Poet.class);
log.info(response.toString());
//使用 fuzzy query,对输入不分词,直接计算模糊选项。
SearchResponse<Poet> response2 = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.fuzzy(fuzzyQueryBuilder -> fuzzyQueryBuilder
.field("success").fuzziness("1").value("理想")))
, Poet.class);
log.info(response2.toString());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
1.2.1.8、wildcard 查询
/**
* wildcard 查询,类似 SQL 语句中的 like;? 匹配一个字符,* 匹配多个字符
*/
@Test
public void searchWildcard() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder.wildcard(wildcardQueryBuilder -> wildcardQueryBuilder
.field("name")
.wildcard("李*")))
, Poet.class);
log.info(response.toString());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
1.2.1.9、bool 查询
/**
* bool 查询,组合查询
*/
@Test
public void searchBool() throws IOException {
//查询 success 包含 “思想” 且 age 在 [20-40] 之间的文档
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.bool(boolQueryBuilder -> boolQueryBuilder
.must(queryBuilder2 -> queryBuilder2
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想"))
)
.must(queryBuilder2 -> queryBuilder2
.range(rangeQueryBuilder -> rangeQueryBuilder
.field("age").gte(JsonData.of("20")).lt(JsonData.of("40")))
)
)
)
, Poet.class);
log.info(response.toString());
//过滤出 success 包含 “思想” 且 age 在 [20-40] 之间的文档,不计算得分
SearchResponse<Poet> response2 = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.bool(boolQueryBuilder -> boolQueryBuilder
.filter(queryBuilder2 -> queryBuilder2
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想"))
)
.filter(queryBuilder2 -> queryBuilder2
.range(rangeQueryBuilder -> rangeQueryBuilder
.field("age").gte(JsonData.of("20")).lt(JsonData.of("40")))
)
)
)
, Poet.class);
log.info(response2.toString());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
1.2.2、aggs 查询
/**
* aggs 查询,聚合查询
*/
@Test
public void searchAggs() throws IOException {
//求和,类似 select sum(age) from poet-index
SearchResponse response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("age_sum", aggregationBuilder -> aggregationBuilder
.sum(sumAggregationBuilder -> sumAggregationBuilder
.field("age")))
, Poet.class);
log.info(response.toString());
//类似 select count distinct(age) from poet-index
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("age_count", aggregationBuilder -> aggregationBuilder
.cardinality(cardinalityAggregationBuilder -> cardinalityAggregationBuilder.field("age")))
, Poet.class);
log.info(response.toString());
//数量、最大、最小、平均、求和
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("age_stats", aggregationBuilder -> aggregationBuilder
.stats(statsAggregationBuilder -> statsAggregationBuilder
.field("age")))
, Poet.class);
log.info(response.toString());
//select name,count(*) from poet-index group by name
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("name_terms", aggregationBuilder -> aggregationBuilder
.terms(termsAggregationBuilder -> termsAggregationBuilder
.field("name")))
, Map.class);
log.info(response.toString());
//select name,age,count(*) from poet-index group by name,age
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("name_terms", aggregationBuilder -> aggregationBuilder
.terms(termsAggregationBuilder -> termsAggregationBuilder
.field("name")
)
.aggregations("age_terms", aggregationBuilder2 -> aggregationBuilder2
.terms(termsAggregationBuilder -> termsAggregationBuilder
.field("age")
))
)
, Poet.class);
log.info(response.toString());
//类似 select avg(age) from poet-index where name='李白'
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.bool(boolQueryBuilder -> boolQueryBuilder
.filter(queryBuilder2 -> queryBuilder2
.term(termQueryBuilder -> termQueryBuilder
.field("name").value("李白")))))
.aggregations("ave_age", aggregationBuilder -> aggregationBuilder
.avg(averageAggregationBuilder -> averageAggregationBuilder.field("age")))
, Poet.class);
log.info(response.toString());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
1.2.3、suggest 查询
/**
* suggest 查询,推荐查询
*/
@Test
public void searchSuggest() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.suggest(suggesterBuilder -> suggesterBuilder
.suggesters("success_suggest", fieldSuggesterBuilder -> fieldSuggesterBuilder
.text("思考")
.term(termSuggesterBuilder -> termSuggesterBuilder
.field("success")
.suggestMode(SuggestMode.Always)
.minWordLength(2)
)
)
)
, Poet.class);
log.info(response.toString());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
1.2.4、highlight
/**
* 高亮显示
*/
@Test
public void searchHighlight() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想")))
.highlight(highlightBuilder -> highlightBuilder
.preTags("<span color='red'>")
.postTags("</span>")
.fields("success", highlightFieldBuilder -> highlightFieldBuilder))
, Poet.class);
log.info(response.toString());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
2、完整代码
package com.abc.demo.es;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.SuggestMode;
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class ElasticsearchJavaCase2 {
private static final String INDEX_NAME = "poet-index";
private ElasticsearchTransport transport;
private ElasticsearchClient client;
@Before
public void before() {
RestClient restClient = RestClient.builder(
new HttpHost("10.49.196.10", 9200),
new HttpHost("10.49.196.11", 9200),
new HttpHost("10.49.196.12", 9200)).build();
ObjectMapper objectMapper = new ObjectMapper();
transport = new RestClientTransport(restClient, new JacksonJsonpMapper(objectMapper));
client = new ElasticsearchClient(transport);
}
@After
public void after() throws IOException {
transport.close();
}
/**
* 查询文档数量
*/
@Test
public void count() throws IOException {
//查询该索引的所有文档数量
CountResponse response = client.count(builder -> builder.index(INDEX_NAME));
log.info("response={}", response);
//通过 Lucene 查询语法指定条件;8.13.4会报错”contains unrecognized parameter: [q]“,因为 API 提交了请求 "{}",应该时不需要请求体
//response = client.count(builder -> builder.index(INDEX_NAME).q("name:杜甫"));
log.info("response={}", response);
//通过 "Query DSL" 指定条件
response = client.count(builder -> builder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.term(termQueryBuilder -> termQueryBuilder
.field("name").value("杜甫")
)
)
);
log.info("response={}", response);
}
/**
* term/terms查询,对输入内容不做分词处理
*/
@Test
public void searchTerm() throws IOException {
SearchResponse<Map> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.term(termQueryBuilder -> termQueryBuilder
.field("name").value("李白")))
.sort(sortOptionsBuilder -> sortOptionsBuilder
.field(fieldSortBuilder -> fieldSortBuilder
.field("age").order(SortOrder.Asc)))
.source(sourceConfigBuilder -> sourceConfigBuilder
.filter(sourceFilterBuilder -> sourceFilterBuilder
.includes("age", "name")))
.from(0)
.size(10)
, Map.class);
log.info("response={}", response);
List<FieldValue> words = new ArrayList<>();
words.add(new FieldValue.Builder().stringValue("李白").build());
words.add(new FieldValue.Builder().stringValue("杜甫").build());
SearchResponse<Poet> response2 = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.terms(termsQueryBuilder -> termsQueryBuilder
.field("name").terms(termsQueryFieldBuilder -> termsQueryFieldBuilder.value(words))))
.source(sourceConfigBuilder -> sourceConfigBuilder
.filter(sourceFilterBuilder -> sourceFilterBuilder
.excludes("about")))
.from(0)
.size(10)
, Poet.class);
log.info("response2={}", response2);
}
/**
* range(范围)查询
*/
@Test
public void searchRange() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.range(rangeQueryBuilder -> rangeQueryBuilder
.field("age").gte(JsonData.of("20")).lt(JsonData.of("40"))))
, Poet.class);
log.info("response={}", response);
}
/**
* exists 查询,查询对应字段不为空的数据
*/
@Test
public void exists() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME).query(builder -> builder.exists(builder1 -> builder1.field("poems")))
, Poet.class);
log.info("response={}", response);
}
/**
* match查询,对输入内容先分词再查询
*/
@Test
public void searchMatch() throws IOException {
SearchResponse<Map> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想")))
, Map.class);
log.info("response={}", response);
}
/**
* multi_match 查询,多个字段进行匹配。
*/
@Test
public void searchMultiMatch() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder
.fields("about", "success").query("思想")))
, Poet.class);
log.info("response={}", response);
}
/**
* match_phrase 查询,类似 match,先把查询字符串分词生成一个词列表,查询包含所有这些词且这些词在文档中出现次序一致的数据。
*/
@Test
public void searchMatchPhrase() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.matchPhrase(matchPhraseQueryBuilder -> matchPhraseQueryBuilder
.field("success").query("伟大作家")))
, Poet.class);
log.info("response={}", response);
}
/**
* match_all 查询,查询所有文档
*/
@Test
public void searchMatchAll() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.matchAll(matchAllQueryBuilder -> matchAllQueryBuilder))
, Poet.class);
log.info("response={}", response);
//不加请求体,也是一样的效果,查询所有文档。
response = client.search(searchRequestBuilder -> searchRequestBuilder.index(INDEX_NAME), Poet.class);
log.info("response={}", response);
}
/**
* match_none 查询,与 match_all 相反,返回 0 个文档。
*/
@Test
public void searchMatchNone() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.matchNone(matchAllQueryBuilder -> matchAllQueryBuilder))
, Poet.class);
log.info("response={}", response);
}
/**
* query_string 查询,可以同时实现多种查询
*/
@Test
public void searchQueryString() throws IOException {
//类似 match
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.defaultField("success").query("古典文学")))
, Poet.class);
log.info("response={}", response);
//类似 mulit_match
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("about", "success").query("古典文学")))
, Poet.class);
log.info("response={}", response);
//类似 match_phrase
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.defaultField("success").query("\"文学作家\"")))
, Poet.class);
log.info(response.toString());
//带运算符查询,运算符两边的词不再分词
//查询同时包含 ”文学“ 和 ”伟大“ 的文档
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("success").query("文学 AND 伟大")))
, Poet.class);
log.info("response={}", response);
//等同上一个查询
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("success").query("文学 伟大").defaultOperator(Operator.And)))
, Poet.class);
log.info("response={}", response);
//查询 name 或 success 字段包含"文学"和"伟大"这两个单词,或者包含"李白"这个单词的文档。
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.queryString(queryStringQueryBuilder -> queryStringQueryBuilder
.fields("name","success").query("(文学 AND 伟大) OR 高度")))
, Poet.class);
log.info("response={}", response);
}
/**
* simple_query_string 查询,类似 query_string,主要区别如下:
* 1、不支持 AND OR NOT,会当做字符处理;使用 + 代替 AND,| 代替 OR,- 代替 NOT
* 2、会忽略错误的语法
*/
@Test
public void searchSimpleQueryString() throws IOException {
//查询同时包含 ”文学“ 和 ”伟大“ 的文档
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.simpleQueryString(simpleQueryStringQueryBuilder -> simpleQueryStringQueryBuilder
.fields("success").query("文学 + 伟大")))
, Poet.class);
log.info("response={}", response);
}
/**
* 模糊查询
*/
@Test
public void searchFuzzy() throws IOException {
//全文查询时使用模糊参数,先分词再计算模糊选项。
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思考").fuzziness("1")))
, Poet.class);
log.info(response.toString());
//使用 fuzzy query,对输入不分词,直接计算模糊选项。
SearchResponse<Poet> response2 = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.fuzzy(fuzzyQueryBuilder -> fuzzyQueryBuilder
.field("success").fuzziness("1").value("理想")))
, Poet.class);
log.info(response2.toString());
}
/**
* wildcard 查询,类似 SQL 语句中的 like;? 匹配一个字符,* 匹配多个字符
*/
@Test
public void searchWildcard() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder.wildcard(wildcardQueryBuilder -> wildcardQueryBuilder
.field("name")
.wildcard("李*")))
, Poet.class);
log.info(response.toString());
}
/**
* bool 查询,组合查询
*/
@Test
public void searchBool() throws IOException {
//查询 success 包含 “思想” 且 age 在 [20-40] 之间的文档
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.bool(boolQueryBuilder -> boolQueryBuilder
.must(queryBuilder2 -> queryBuilder2
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想"))
)
.must(queryBuilder2 -> queryBuilder2
.range(rangeQueryBuilder -> rangeQueryBuilder
.field("age").gte(JsonData.of("20")).lt(JsonData.of("40")))
)
)
)
, Poet.class);
log.info(response.toString());
//过滤出 success 包含 “思想” 且 age 在 [20-40] 之间的文档,不计算得分
SearchResponse<Poet> response2 = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.bool(boolQueryBuilder -> boolQueryBuilder
.filter(queryBuilder2 -> queryBuilder2
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想"))
)
.filter(queryBuilder2 -> queryBuilder2
.range(rangeQueryBuilder -> rangeQueryBuilder
.field("age").gte(JsonData.of("20")).lt(JsonData.of("40")))
)
)
)
, Poet.class);
log.info(response2.toString());
}
/**
* aggs 查询,聚合查询
*/
@Test
public void searchAggs() throws IOException {
//求和,类似 select sum(age) from poet-index
SearchResponse response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("age_sum", aggregationBuilder -> aggregationBuilder
.sum(sumAggregationBuilder -> sumAggregationBuilder
.field("age")))
, Poet.class);
log.info(response.toString());
//类似 select count distinct(age) from poet-index
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("age_count", aggregationBuilder -> aggregationBuilder
.cardinality(cardinalityAggregationBuilder -> cardinalityAggregationBuilder.field("age")))
, Poet.class);
log.info(response.toString());
//数量、最大、最小、平均、求和
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("age_stats", aggregationBuilder -> aggregationBuilder
.stats(statsAggregationBuilder -> statsAggregationBuilder
.field("age")))
, Poet.class);
log.info(response.toString());
//select name,count(*) from poet-index group by name
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("name_terms", aggregationBuilder -> aggregationBuilder
.terms(termsAggregationBuilder -> termsAggregationBuilder
.field("name")))
, Map.class);
log.info(response.toString());
//select name,age,count(*) from poet-index group by name,age
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.aggregations("name_terms", aggregationBuilder -> aggregationBuilder
.terms(termsAggregationBuilder -> termsAggregationBuilder
.field("name")
)
.aggregations("age_terms", aggregationBuilder2 -> aggregationBuilder2
.terms(termsAggregationBuilder -> termsAggregationBuilder
.field("age")
))
)
, Poet.class);
log.info(response.toString());
//类似 select avg(age) from poet-index where name='李白'
response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.bool(boolQueryBuilder -> boolQueryBuilder
.filter(queryBuilder2 -> queryBuilder2
.term(termQueryBuilder -> termQueryBuilder
.field("name").value("李白")))))
.aggregations("ave_age", aggregationBuilder -> aggregationBuilder
.avg(averageAggregationBuilder -> averageAggregationBuilder.field("age")))
, Poet.class);
log.info(response.toString());
}
/**
* suggest 查询,推荐搜索
*/
@Test
public void searchSuggest() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.suggest(suggesterBuilder -> suggesterBuilder
.suggesters("success_suggest", fieldSuggesterBuilder -> fieldSuggesterBuilder
.text("思考")
.term(termSuggesterBuilder -> termSuggesterBuilder
.field("success")
.suggestMode(SuggestMode.Always)
.minWordLength(2)
)
)
)
, Poet.class);
log.info(response.toString());
}
/**
* 高亮显示
*/
@Test
public void searchHighlight() throws IOException {
SearchResponse<Poet> response = client.search(searchRequestBuilder -> searchRequestBuilder
.index(INDEX_NAME)
.query(queryBuilder -> queryBuilder
.match(matchQueryBuilder -> matchQueryBuilder
.field("success").query("思想艺术")))
.highlight(highlightBuilder -> highlightBuilder
.preTags("<span color='red'>")
.postTags("</span>")
.fields("success", highlightFieldBuilder -> highlightFieldBuilder))
, Poet.class);
log.info(response.toString());
}
@Data
@AllArgsConstructor
@NoArgsConstructor
static class Poet {
private Integer age;
private String name;
private String poems;
private String about;
/**成就*/
private String success;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
- 335.
- 336.
- 337.
- 338.
- 339.
- 340.
- 341.
- 342.
- 343.
- 344.
- 345.
- 346.
- 347.
- 348.
- 349.
- 350.
- 351.
- 352.
- 353.
- 354.
- 355.
- 356.
- 357.
- 358.
- 359.
- 360.
- 361.
- 362.
- 363.
- 364.
- 365.
- 366.
- 367.
- 368.
- 369.
- 370.
- 371.
- 372.
- 373.
- 374.
- 375.
- 376.
- 377.
- 378.
- 379.
- 380.
- 381.
- 382.
- 383.
- 384.
- 385.
- 386.
- 387.
- 388.
- 389.
- 390.
- 391.
- 392.
- 393.
- 394.
- 395.
- 396.
- 397.
- 398.
- 399.
- 400.
- 401.
- 402.
- 403.
- 404.
- 405.
- 406.
- 407.
- 408.
- 409.
- 410.
- 411.
- 412.
- 413.
- 414.
- 415.
- 416.
- 417.
- 418.
- 419.
- 420.
- 421.
- 422.
- 423.
- 424.
- 425.
- 426.
- 427.
- 428.
- 429.
- 430.
- 431.
- 432.
- 433.
- 434.
- 435.
- 436.
- 437.
- 438.
- 439.
- 440.
- 441.
- 442.
- 443.
- 444.
- 445.
- 446.
- 447.
- 448.
- 449.
- 450.
- 451.
- 452.
- 453.
- 454.
- 455.
- 456.
- 457.
- 458.
- 459.
- 460.
- 461.
- 462.
- 463.
- 464.
- 465.
- 466.
- 467.
- 468.
- 469.
- 470.
- 471.
- 472.
- 473.
- 474.
- 475.
- 476.
- 477.
- 478.
- 479.
- 480.
- 481.
- 482.
- 483.
- 484.
- 485.
- 486.
- 487.
- 488.
- 489.
ElasticsearchJavaCase2.java
详细的 Elasticsearch Java API Client 使用说明,请参考官网文档:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html。