目录
- 一、前言
- 二、Jest client和Rest client使用
- 2.1、Rest client方式
- 三、Rest client方式
- 3.1、基本操作
- 3.2、联合查询
- 3.3、多关键字查询
一、前言
ES有4种客户端,分别是:Jest client、Rest client、Transport client、Node client。
ES支持两种协议
HTTP协议,支持的客户端有Jest client和Rest client
Native Elasticsearch binary协议,也就是Transport client【7.0弃用】和Node client【2.3弃用】
Jest client非官方支持,在ES5.0之前官方提供的客户端只有Transport client、Node client。在5.0之后官方发布Rest client【推荐使用】。
二、Jest client和Rest client使用
2.1、Rest client方式
sptingboot2.0版本引用jar包
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.15.0</version>
</dependency>
<!-- elasticsearch -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>com.hankcs</groupId>
<artifactId>hanlp</artifactId>
<version>portable-1.7.5</version>
</dependency>
pom文件配置
#es配置
es.enable=true
es.hostUrl=**
es.port=9200
es.protocol=http
es.connectTimeOut=1000
es.socketTimeOut=30000
es.connectionRequestTimeOut=500
es.maxConnectNum=100
es.maxConnectPerRoute=100
es.username=***
es.password=***
RestHighLevelClient的config如下:
@Configuration
public class ElasticClient {
@Value("${es.hostUrl}")
private String hostUrl;
@Value("${es.port}")
private int port;
@Value("${es.protocol}")
private String protocol;
@Value("${es.connectTimeOut}")
private int connectTimeOut;
@Value("${es.socketTimeOut}")
private int socketTimeOut;
@Value("${es.connectionRequestTimeOut}")
private int connectionRequestTimeOut;
@Value("${es.maxConnectNum}")
private int maxConnectNum;
@Value("${es.maxConnectPerRoute}")
private int maxConnectPerRoute;
@Value("${es.username}")
private String username;
@Value("${es.password}")
private String password;
@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostUrl, port, protocol));
restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.setMaxConnTotal(maxConnectNum);
httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
return httpClientBuilder;
}
});
//请求配置
restClientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
requestConfigBuilder.setConnectTimeout(connectTimeOut);
requestConfigBuilder.setSocketTimeout(socketTimeOut);
requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
return requestConfigBuilder;
}
});
return new RestHighLevelClient(restClientBuilder);
}
}
三、Rest client方式
3.1、基本操作
@Data
public abstract class BaseEsDo implements Serializable {
/**
* ES的INDEX
*/
@JSONField(name = "index")
private String index;
/**
* ES唯一值ID
*/
@JSONField(name = "id")
private String id;
/**
* 创建时间
*/
@JSONField(name = "create_time", format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 修改时间
*/
@JSONField(name = "update_time", format = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 文档状态
*/
@JSONField(name = "doc_state")
private Boolean docState;
/**
* 文档版本
*/
@JSONField(name = "doc_version")
private Integer docVersion;
/**
* 文档备注
*/
@JSONField(name = "doc_remarks")
private String docRemarks;
/**
* 文档查看数量
*/
@JSONField(name = "doc_view_number")
private int docViewNumber;
/**
* 文档删除状态,默认true
*/
@JSONField(name = "doc_delete")
private boolean docDelete = false;
}
AbstractElasticRepository类是封装的常见ES操作
@Repository
@Slf4j
public abstract class AbstractElasticRepository<T extends BaseEsDo> {
@Autowired
protected RestHighLevelClient client;
@Autowired
private JestClient jestClient; //后续研究
/**
* 全量匹配查询 【默认返回10条记录】
* @param index
* @return
*/
public <T extends BaseEsDo> List<T> queryMatchAll(String index, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);//指定要查询的索引
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
searchSourceBuilder.query(matchAllQueryBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("花费的时长:" + searchResponse.getTook());
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 分页查询、倒序或降序、指定需要返回或者排除的字段
* sortMap:不能传多个,只能传一个排序
* @throws IOException
*/
public <T extends BaseEsDo> List<T> pageQuery(String index, int from, int size, Map<String,SortOrder> sortMap, String[] includes,
String[] excludes, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);//指定要查询的索引
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery());
//设置分页
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//倒序或降序
if(!sortMap.isEmpty()){
sortMap.forEach((k,v)->searchSourceBuilder.sort(k,v));
// searchSourceBuilder.sort("age", SortOrder.DESC);
}
//指定需要返回或者排除的字段
// String[] includes = {"id", "name"};
// String[] excludes = {};
if(null != includes || null != excludes)
searchSourceBuilder.fetchSource(includes, excludes);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("花费的时长:" + searchResponse.getTook());
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 关键字匹配 【input会分词】
* 按照要求去相关field去匹配,类似模糊匹配
* @param index
* @param input
* @param fields
* @param clazz
* @param <T>
* @return
* @throws IOException
*/
public <T extends BaseEsDo> List<T> stringQuery(String index, String input, List<String> fields, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//关键词查找 【会分词】
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(input); //默认查询所有field
if(CollectionUtils.isNotEmpty(fields)){
fields.forEach(l->queryStringQueryBuilder.field(l));
}
searchSourceBuilder.query(queryStringQueryBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* match 查找
* 【只能是一个字段, 值可以多个,分词后类似模糊查询】
*/
public <T extends BaseEsDo> List<T> matchQuery(String index, String fieldName, String fieldValue, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//match 查找
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(fieldName, fieldValue);
matchQueryBuilder.operator(Operator.OR);
searchSourceBuilder.query(matchQueryBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 可以根据字段类型,决定是否使用分词查询,得分最高的在前面。
* 【支持关键字分词,分词后去多个字段进行匹配】
* @param index
* @return
* @throws IOException
*/
public <T extends BaseEsDo> List<T> multiMatchQuery(String index, String input, String[] fieldNames, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//match 查找
//例如 QueryBuilders.multiMatchQuery("王者辅助","address", "desc")
MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(input,fieldNames);
multiMatchQuery.operator(Operator.OR);
searchSourceBuilder.query(multiMatchQuery);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 精准查询
* 只匹配一个field字段,传一个input,但不会被分词
* @param index
* @param
* @return
* @throws IOException
*/
public <T extends BaseEsDo> List<T> termQuery(String index, String fieldName, String input, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查找
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(fieldName+".keyword",input);
searchSourceBuilder.query(termQueryBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
private QueryBuilder booleanQuery(List<QueryBuilder> termList){
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for(QueryBuilder te : termList){
boolQueryBuilder.should(te);
}
return boolQueryBuilder;
}
/**
* 多个字段精准匹配
* 使用should方式---测试发现像and结果
* @param index
* @param matchMap
* @param clazz
* @param <T>
* @return
* @throws IOException
*/
public <T extends BaseEsDo> List<T> multiOrTermQuery(String index, Map<String,Object> matchMap, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查找
if(!matchMap.isEmpty()){
List<QueryBuilder> termList = new ArrayList<>();
matchMap.forEach((k,v)->termList.add(QueryBuilders.termQuery(k, v)));
searchSourceBuilder.query(booleanQuery(termList));
}
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 范围查询
* @throws IOException
*/
public <T extends BaseEsDo> List<T> rangeQuery(String index, String filed, Object left, Object right, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//Range 查找
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(filed);
rangeQueryBuilder.gte(left);
rangeQueryBuilder.lt(right);
searchSourceBuilder.query(rangeQueryBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 多id查询
* @throws IOException
*/
public <T extends BaseEsDo> List<T> multiIdQuery(String index, List<String> ids, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//多个id 查找
IdsQueryBuilder idsQueryBuilder = QueryBuilders.idsQuery();
idsQueryBuilder.addIds((String[])ids.toArray());
searchSourceBuilder.query(idsQueryBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 高亮查询
* matchMap: key是关键字,v:是多字段
*/
public <T extends BaseEsDo> List<T> highlightQuery(String index, String input, String[] fieldNames, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//自定义 多字段高亮 查找
MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(input,fieldNames);
multiMatchQuery.operator(Operator.OR);
searchSourceBuilder.query(multiMatchQuery);
HighlightBuilder highlightBuilder = new HighlightBuilder();
for(String te : fieldNames){
highlightBuilder.field(te);
}
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");
highlightBuilder.requireFieldMatch(false); //多字段时,需要设置为false
searchSourceBuilder.highlighter(highlightBuilder);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("花费的时长:" + searchResponse.getTook());
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(p -> {
System.out.println("文档原生信息:" + p.getSourceAsString());
System.out.println("高亮信息:" + p.getHighlightFields());
// //获取高亮字段
// Map<String, HighlightField> highlightFields = p.getHighlightFields();
});
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* 模糊查询 --都不会分词
* fuzzyQuery: 左右模糊查询 【不分词,fuzziness的参数作用是在查询时,es动态的将查询关键词前后增加或者删除一个词,然后进行匹配】
* prefixQuery:前缀查询
* 通配符查询,支持*和?,?表示单个字符
* @param index
* @return
* @throws IOException
*/
public <T extends BaseEsDo> List<T> vagueQuery(String index, String input, String fieldName, Integer type, Class<T> clazz) throws IOException{
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(index);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
if(type == 1){
//Fuzzy 查找
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery(fieldName, input).fuzziness(Fuzziness.ONE);
searchSourceBuilder.query(fuzzyQueryBuilder);
}else if(type == 2){
PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery(fieldName, input);
searchSourceBuilder.query(prefixQueryBuilder);
}else if(type == 3){
//有点类似 规定好某种格式,进行搜索
// QueryBuilders.wildcardQuery(“title”, “开*放”)
//QueryBuilders.wildcardQuery(“title”, “开?放”)
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(fieldName, input);
searchSourceBuilder.query(wildcardQueryBuilder);
}
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
List<T> list = Arrays.stream(hits.getHits())
.map(searchHit ->JSON.parseObject(JSON.toJSONString(searchHit.getSourceAsMap()), clazz))
.collect(Collectors.toList());
return list;
}
/**
* ik分词
* @param text 文本
*/
public List<String> getAnalyze(String text) throws IOException {
text = text.length() > 100 ? text.substring(0, 100) : text;
return getAnalyze(text, "ik_max_word");
}
/**
* ik分词
* @param text 文本
* @param analyzer 分词器
*/
public List<String> getAnalyze(String text, String analyzer) throws IOException {
Request request = new Request("GET", "_analyze");
JSONObject entity = new JSONObject();
entity.put("analyzer", analyzer);
entity.put("text", text);
request.setJsonEntity(entity.toJSONString());
Response response = this.client.getLowLevelClient().performRequest(request);
JSONObject tokens = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
JSONArray arrays = tokens.getJSONArray("tokens");
List<String> list = new ArrayList<String>();
for (int i = 0; i < arrays.size(); i++) {
JSONObject obj = JSON.parseObject(arrays.getString(i));
list.add(obj.getString("token"));
}
return list;
}
}
具体业务类TestElasticRepository
@Repository
public class TestElasticRepository extends AbstractElasticRepository<TestEsDo> {
public RestHighLevelClient getClient(){
return client;
}
}
常见的使用方式
public void queryMatchAll(){
try{
testElasticRepository.queryMatchAll(TEST_INDEX,TestEsDo.class);
Map<String,SortOrder> sortMap = new HashMap<>();
sortMap.put("age",SortOrder.DESC);
testElasticRepository.pageQuery(TEST_INDEX,1,3,sortMap,null,null,TestEsDo.class);
testElasticRepository.stringQuery(TEST_INDEX,"城市",Arrays.asList("description","test_name"),TestEsDo.class);
testElasticRepository.termQuery(TEST_INDEX,"test_name","上海",TestEsDo.class);
List<String> wordList = testElasticRepository.getAnalyze("历史城市");
System.out.println("wordList: "+JSON.toJSONString(wordList)); //wordList: ["历史","城市"]
//这里匹配就是根据分词然后查询description字段
testElasticRepository.matchQuery(TEST_INDEX,"description","历史城市",TestEsDo.class);
String[] vaStr1 = new String[]{"description","test_name"};
//"京城市"分词后,然后对description、test_name字段进行匹配查询,得分高的在前面,默认返回10条
testElasticRepository.multiMatchQuery(TEST_INDEX,"京城市",vaStr1,TestEsDo.class);
testElasticRepository.highlightQuery(TEST_INDEX,"京城市",vaStr1,TestEsDo.class);
testElasticRepository.vagueQuery(TEST_INDEX,"历史","description",1,TestEsDo.class);
Map<String,Object> matchMap5 = new HashMap<>();
matchMap5.put("age",200);
matchMap5.put("test_name","南京");
testElasticRepository.multiOrTermQuery(TEST_INDEX,matchMap5,TestEsDo.class);
}catch (Exception e){
log.error("queryMatchAll e:{}",e.getMessage());
}
}
3.2、联合查询
一般ES的步骤是:
SearchRequest searchRequest = new SearchRequest(index); //指定要查询的索引
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //创建 SearchSourceBuilder条件构造
MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(input,fieldNames); //match 查找条件
multiMatchQuery.operator(Operator.OR);
searchSourceBuilder.query(multiMatchQuery); //match查找条件 赋给 SearchSourceBuilder
searchRequest.source(searchSourceBuilder); //将 SearchSourceBuilder 添加到 SearchRequest中
BoolQueryBuilder查询:
must: 文档必须匹配must所包括的查询条件,相当于 “AND”
should: 文档应该匹配should所包括的查询条件其中的一个或多个,相当于 “OR”
must_not: 文档不能匹配must_not所包括的该查询条件,相当于“NOT”
现在有需求查询两个表,它们有各自的条件
public void multiTableQuery(String searchContent,String knowledgeClassificationNo,String startTe,String endTe){
BoolQueryBuilder boolBuilder = new BoolQueryBuilder();
boolBuilder.should(getKnowledgeBoolBuilder(searchContent,knowledgeClassificationNo,startTe,endTe));
boolBuilder.should(getFileBoolBuilder(searchContent,knowledgeClassificationNo,startTe,endTe));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(boolBuilder); //设置查询条件
boolBuilder.should().forEach(k->{
BoolQueryBuilder te = (BoolQueryBuilder)k;
log.info("boolBuilder:{}", JSON.toJSONString(te.must()));
});
//设置高亮显示
ElasticQueryBuilder.setHighlight(searchSourceBuilder);
//设置分页
ElasticQueryBuilder.setPage(searchSourceBuilder, new Pagination());
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(searchSourceBuilder);
// es搜索
try {
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(p -> {
System.out.println("文档原生信息:" + p.getSourceAsString());
System.out.println("高亮信息:" + p.getHighlightFields());
// //获取高亮字段
// Map<String, HighlightField> highlightFields = p.getHighlightFields();
});
for (SearchHit searchHit : hits.getHits()) {
Map<String, Object> map = searchHit.getSourceAsMap();
System.out.println("multiQuery:" + JSON.toJSONString(map));
}
}catch (Exception e){
}
}
private BoolQueryBuilder getKnowledgeBoolBuilder(String searchContent,String knowledgeClassificationNo,String startTe,String endTe){
//查询条件
BoolQueryBuilder knowledgeBoolBuilder = QueryBuilders.boolQuery();
//knowledgeBoolBuilder must()
knowledgeBoolBuilder.must(ElasticQueryBuilder.term("sid", "665555"));
MultiMatchQueryBuilder kMultiMatchQueryBuilder = new MultiMatchQueryBuilder(searchContent,
"name", "tag.tag_name", "desc").boost(3);
//knowledgeBoolBuilder must()
knowledgeBoolBuilder.must(kMultiMatchQueryBuilder);
//knowledgeBoolBuilder must()
knowledgeBoolBuilder.must(ElasticQueryBuilder.term("type.classification_no.keyword", knowledgeClassificationNo));
//knowledgeBoolBuilder must()
List<String> tagNos = Arrays.asList("654444","333555","55433");
knowledgeBoolBuilder.must(ElasticQueryBuilder.termsKeyword("tag.tag_no", tagNos));
Date startTime = TimeUtil.stringToDate(startTe,"yyyy-MM-dd HH:mm:ss");
Date endTime = TimeUtil.stringToDate(endTe,"yyyy-MM-dd HH:mm:ss");
RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("create_time.keyword").gte(startTime).lte(endTime);
//knowledgeBoolBuilder must()
knowledgeBoolBuilder.must(rangeQueryBuilder);
//knowledgeBoolBuilder must()
knowledgeBoolBuilder.must(ElasticQueryBuilder.term("doc_delete", false));
//knowledgeBoolBuilder must()
knowledgeBoolBuilder.must(QueryBuilders.termQuery("_index", "knowledge"));
return knowledgeBoolBuilder;
}
3.3、多关键字查询
输入是多个关键字,不分词,对某个ES字段进行查询
ES表test_word_matrix的结构如下,输入List<>,对wordMatrix字段进行匹配,按照top顺序高低返回。
{
“_index”: “test_word_matrix”,
“_type”: “_doc”,
“_id”: “a4e780c2-2744-46de-8f66-5462e3b7e051”,
“_version”: 1,
“_seq_no”: 0,
“_primary_term”: 1,
“found”: true,
“_source”: {
“answer”: “工作原理是:接完可往里面倒胃口我们的思考时代大厦”,
“basic_problem”: “MG ONE车型中ETC系统的激活原理”,
“create_time”: “2023-07-17 16:53:21”,
“doc_delete”: false,
“doc_view_number”: 0,
“id”: “a4e780c2-2744-46de-8f66-5462e3b7e051”,
“index”: “test_word_matrix”,
“origin_problem”: “MGONE ETC系统 激活原理”,
“update_time”: “2023-07-17 16:53:21”,
“wordMatrix”: [
“中”,
“ETC”,
“车型”,
“系统”,
“ONE”,
“激活”,
“原理”,
“MG”
]
}
}
public String queryWordMatrix(List<String> wordMa){
//查询条件
BoolQueryBuilder wordMatrixBuiler = QueryBuilders.boolQuery();
wordMatrixBuiler.must(ElasticQueryBuilder.termsKeyword("wordMatrix", wordMa));
wordMatrixBuiler.must(QueryBuilders.termQuery("_index", TEST_WORD_MATRIX_INDEX));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(wordMatrixBuiler); //设置查询条件
//设置高亮显示
ElasticQueryBuilder.setHighlight(searchSourceBuilder);
//设置分页
ElasticQueryBuilder.setPage(searchSourceBuilder, new Pagination());
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(searchSourceBuilder);
// es搜索
try {
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(p -> {
System.out.println("文档原生信息:" + p.getSourceAsString());
System.out.println("高亮信息:" + p.getHighlightFields());
// //获取高亮字段
// Map<String, HighlightField> highlightFields = p.getHighlightFields();
});
for (SearchHit searchHit : hits.getHits()) {
Map<String, Object> map = searchHit.getSourceAsMap();
System.out.println("multiQuery:" + JSON.toJSONString(map));
}
return JSON.toJSONString(hits.getHits());
}catch (Exception e){
}
return null;
}