es全表查询
需求:
根据关键字匹配某张表所有字段数据,进行并进行高亮显示。使用模糊查询
解决思路:
- 查询索引所有字段
- 拼接查询条件
- 解析查询条件
遇到的问题:
- 电话号码也要求高亮,但是因为电话号码是不分词的,所以这里我们使用 keyword类型和wildcardQuery配合使用。keyword类型是不支持高亮的,所以我们写了一个手动高亮的方法
- 想要做到mysql的like的作用使用matchPhrcaseQuery的短语匹配
代码:
1.查询索引的所有字段(获取索引结构)
private String[] getMappingStructure(RestHighLevelClient client, String Mapping) {
//获取索引结构
GetMappingsRequest request = new GetMappingsRequest();
request.indices(Mapping);
GetMappingsResponse mapping = null;
try {
mapping = client.indices().getMapping(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
AtomicReference<String> sb = new AtomicReference<>("");
mapping.mappings().forEach((k,v)->{
v.getSourceAsMap().forEach((k2,v2)->{
sb.set(v2.toString());
});
});
String sb2 = sb.toString().substring(1,sb.toString().length()-1);
String[] split = sb2.split("}, ");
List<String> strings = Arrays.asList(split);
ArrayList<String> arr = new ArrayList<>();
strings.forEach(s->{
if (s.indexOf("text") != -1){
String ss = s.split("=")[0];
if (!"id".equals(ss)){
if (!"zc_area".equals(ss)){
arr.add(ss);
}
}
}
});
String[] sple2 = arr.toArray(new String[arr.size()]);
return sple2;
}
2.拼接查询条件
//构建分页条件
Integer startIndex = ( current - 1 ) * size;
//获取索引结构
String[] sple2 = getMappingStructure(client, Mapping);
// 1.准备Request
SearchRequest request2 = new SearchRequest(Mapping);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);;
//布尔查询
BoolQueryBuilder builder = new BoolQueryBuilder();
String uscc = "";
String legal_rep_tel = "";
// 2.准备DSL
for (String s : sple2) {
if ("uscc".equals(s) || "legal_rep_tel".equals(s)){
builder.should(QueryBuilders.wildcardQuery(s+".keyword","*"+search+"*"));
}else{
builder.should(QueryBuilders.matchPhraseQuery(s,search));
}
}
searchSourceBuilder.query(builder);
//拼接分页
searchSourceBuilder.from(startIndex).size(size);
// 2.2、指定高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
for (String s : sple2) {
highlightBuilder.field(s)
.preTags(start)
.postTags(end);
searchSourceBuilder.highlighter(highlightBuilder);
}
request2.source().sort("dwmc.keyword", SortOrder.ASC);
request2.source(searchSourceBuilder);
// 3.发送请求
SearchResponse response = null;
try {
response = client.search(request2, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
3.解析响应数据
public String getRed(String str,String search){
if (str.contains(search)){
int i = str.indexOf(search);
String substring = str.substring(0, i);
String substring1 = str.substring(i, i + search.length());
String substring2 = str.substring(i + search.length(), str.length());
substring2 = getRed(substring2,search);
StringBuilder sb = new StringBuilder();
sb.append(substring);
sb.append(start);
sb.append(substring1);
sb.append(end);
sb.append(substring2);
return sb.toString();
}
return "";
}
//解析响应数据
private Page<AdsQiyeBasicInfoES> getAdsQiyeBasicInfoESPage(Integer current, Integer size, String[] sple2, SearchResponse response,String search) {
SearchHits hits = response.getHits();
//总记录数
long value = hits.getTotalHits().value;
List<AdsQiyeBasicInfoES> list = new ArrayList<>();
for (SearchHit hit : hits.getHits()) {
//响应数据转对象
AdsQiyeBasicInfoES adsQiyeBasicInfoES = JSONUtil.toBean(hit.getSourceAsString().toString(), AdsQiyeBasicInfoES.class);
//解析高亮部分数据,使用反射赋值
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
for (String s : sple2) {
// 根据字段名获取高亮结果
HighlightField highlightField = highlightFields.get(s);
if (highlightField != null) {
// 获取高亮值
String v = highlightField.getFragments()[0].string();
try {
Field declaredField = adsQiyeBasicInfoES.getClass().getDeclaredField(s);
declaredField.setAccessible(true);
declaredField.set(adsQiyeBasicInfoES,v);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
//不能分词数据进行手动高亮
String uscc = adsQiyeBasicInfoES.getUscc();
String legalRepTel = adsQiyeBasicInfoES.getLegal_rep_tel();
if (uscc != null && legalRepTel != null){
if (uscc.contains(search)){
uscc = getRed(uscc,search);
}
if (legalRepTel.contains(search)){
legalRepTel = getRed(legalRepTel,search);
}
adsQiyeBasicInfoES.setUscc(uscc);
adsQiyeBasicInfoES.setLegal_rep_tel(legalRepTel);
}
list.add(adsQiyeBasicInfoES);
}
//封装响应数据
Page<AdsQiyeBasicInfoES> page = new Page<>(current, size, value);
page.setRecords(list);
return page;
}
完整代码
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.springem.citybrain.controller.vo.AdsQiyeBasicInfoEsVo;
import com.springem.citybrain.dao.entity.AdsQiyeBasicInfoES;
import com.springem.citybrain.service.ElasticsearchService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.GetMappingsResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@Service
public class ElasticsearchServiceImpl implements ElasticsearchService {
private static final String indexName = "*********";
private static final String start = "<font color='red'>";
private static final String end = "</font>";
@Autowired
private RestHighLevelClient restHighLevelClient;
@Override
public Page<AdsQiyeBasicInfoES> seach(AdsQiyeBasicInfoEsVo vo) {
return getAdsQiyeBasicInfoBySearch(restHighLevelClient,indexName,vo.getSearch(),vo.getCurrent(),vo.getSize());
}
public Page<AdsQiyeBasicInfoES> getAdsQiyeBasicInfoBySearch(RestHighLevelClient client, String Mapping, String search, Integer current, Integer size) {
//构建分页条件
Integer startIndex = ( current - 1 ) * size;
//获取索引结构
String[] sple2 = getMappingStructure(client, Mapping);
// 1.准备Request
SearchRequest request2 = new SearchRequest(Mapping);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);;
//布尔查询
BoolQueryBuilder builder = new BoolQueryBuilder();
String uscc = "";
String legal_rep_tel = "";
// 2.准备DSL
for (String s : sple2) {
if ("uscc".equals(s) || "legal_rep_tel".equals(s)){
builder.should(QueryBuilders.wildcardQuery(s+".keyword","*"+search+"*"));
}else{
builder.should(QueryBuilders.matchPhraseQuery(s,search));
}
}
searchSourceBuilder.query(builder);
//拼接分页
searchSourceBuilder.from(startIndex).size(size);
// 2.2、指定高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
for (String s : sple2) {
highlightBuilder.field(s)
.preTags(start)
.postTags(end);
searchSourceBuilder.highlighter(highlightBuilder);
}
request2.source().sort("dwmc.keyword", SortOrder.ASC);
request2.source(searchSourceBuilder);
// 3.发送请求
SearchResponse response = null;
try {
response = client.search(request2, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
//解析响应数据
Page<AdsQiyeBasicInfoES> page = getAdsQiyeBasicInfoESPage(current, size, sple2, response,search);
return page;
}
public String getRed(String str,String search){
if (str.contains(search)){
int i = str.indexOf(search);
String substring = str.substring(0, i);
String substring1 = str.substring(i, i + search.length());
String substring2 = str.substring(i + search.length(), str.length());
substring2 = getRed(substring2,search);
StringBuilder sb = new StringBuilder();
sb.append(substring);
sb.append(start);
sb.append(substring1);
sb.append(end);
sb.append(substring2);
return sb.toString();
}
return "";
}
//解析响应数据
private Page<AdsQiyeBasicInfoES> getAdsQiyeBasicInfoESPage(Integer current, Integer size, String[] sple2, SearchResponse response,String search) {
SearchHits hits = response.getHits();
//总记录数
long value = hits.getTotalHits().value;
List<AdsQiyeBasicInfoES> list = new ArrayList<>();
for (SearchHit hit : hits.getHits()) {
//响应数据转对象
AdsQiyeBasicInfoES adsQiyeBasicInfoES = JSONUtil.toBean(hit.getSourceAsString().toString(), AdsQiyeBasicInfoES.class);
//解析高亮部分数据,使用反射赋值
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
for (String s : sple2) {
// 根据字段名获取高亮结果
HighlightField highlightField = highlightFields.get(s);
if (highlightField != null) {
// 获取高亮值
String v = highlightField.getFragments()[0].string();
try {
Field declaredField = adsQiyeBasicInfoES.getClass().getDeclaredField(s);
declaredField.setAccessible(true);
declaredField.set(adsQiyeBasicInfoES,v);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
//不能分词数据进行手动高亮
String uscc = adsQiyeBasicInfoES.getUscc();
String legalRepTel = adsQiyeBasicInfoES.getLegal_rep_tel();
if (uscc != null && legalRepTel != null){
if (uscc.contains(search)){
uscc = getRed(uscc,search);
}
if (legalRepTel.contains(search)){
legalRepTel = getRed(legalRepTel,search);
}
adsQiyeBasicInfoES.setUscc(uscc);
adsQiyeBasicInfoES.setLegal_rep_tel(legalRepTel);
}
list.add(adsQiyeBasicInfoES);
}
//封装响应数据
Page<AdsQiyeBasicInfoES> page = new Page<>(current, size, value);
page.setRecords(list);
return page;
}
//获取索引结构
private String[] getMappingStructure(RestHighLevelClient client, String Mapping) {
//获取索引结构
GetMappingsRequest request = new GetMappingsRequest();
request.indices(Mapping);
GetMappingsResponse mapping = null;
try {
mapping = client.indices().getMapping(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
AtomicReference<String> sb = new AtomicReference<>("");
mapping.mappings().forEach((k,v)->{
v.getSourceAsMap().forEach((k2,v2)->{
sb.set(v2.toString());
});
});
String sb2 = sb.toString().substring(1,sb.toString().length()-1);
String[] split = sb2.split("}, ");
List<String> strings = Arrays.asList(split);
ArrayList<String> arr = new ArrayList<>();
strings.forEach(s->{
if (s.indexOf("text") != -1){
String ss = s.split("=")[0];
//筛选出不要的字段
if (!"id".equals(ss)){
if (!"zc_area".equals(ss)){
arr.add(ss);
}
}
}
});
String[] sple2 = arr.toArray(new String[arr.size()]);
return sple2;
}
}
标签:search,sb,String,org,查询,new,import,es
From: https://www.cnblogs.com/fengziHHH/p/16987355.html