1.pom文件
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.1.1</version>
</dependency>
2.配置文件和配置类
server.port=8040
#服务名
spring.application.name=provide-search
#=====ElasticSearch start======
elasticsearch.username=elastic
elasticsearch.password=elastic
elasticsearch.uris=127.0.0.1:9200
配置文件类
@Getter
@Setter
@PropertySource(value="classpath:application.properties")
@Configuration
public class ESProperties {
//用户名
@Value("${elasticsearch.username}")
private String username;
//密码
@Value("${elasticsearch.password}")
private String password;
//Elasticsearch http访问路径
@Value("${elasticsearch.uris}")
private String httpHost;
}
初始化es配置
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Configuration
public class ElasticsearchConfig {
private final ESProperties esProperties;
@Bean
public RestHighLevelClient clientDev() {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(
esProperties.getUsername(), esProperties.getPassword()
));
// 初始化ES客户端的构造器
RestClientBuilder builder = RestClient.builder(httpHostHandlerDev());
// 异步的请求配置
builder.setRequestConfigCallback(builder1 -> {
return builder1;
});
// 异步的httpclient连接数配置
builder.setHttpClientConfigCallback(httpAsyncClientBuilder -> {
// 赋予连接凭证
httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
return httpAsyncClientBuilder;
});
return new RestHighLevelClient(builder);
}
/**
* 为了应对集群部署的es,使用以下写法,返回HttpHost数组
*/
private HttpHost[] httpHostHandlerDev() {
String[] hosts = esProperties.getHttpHost().split(",");
HttpHost[] httpHosts = new HttpHost[hosts.length];
for (int i = 0; i < hosts.length; i++) {
String ip = hosts[i].split(":")[0];
int port = Integer.parseInt(hosts[i].split(":")[1]);
httpHosts[i] = new HttpHost(ip, port, "http");
}
return httpHosts;
}
}
3.查询model模板 ,插入模板
@Data
@ApiModel(value = "es插入")
public class ESInsert implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "索引名称")
public String indexName;
@ApiModelProperty(value = "插入对象")
public List<JSONObject> jsonList;
}
查询模板
@Data
public class ESParam implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "索引名称")
public String indexName;
@ApiModelProperty(value = "开始页码")
public Integer pageNum;
@ApiModelProperty(value = "每页数据量")
public Integer pageSize;
@ApiModelProperty(value = "查询高亮字段名")
public String highName;
@ApiModelProperty(value = "精确查询参数map 参数and连接")
public Map<String,Object> andMap;
@ApiModelProperty(value = "精确查询参数map 参数or连接")
public Map<String,Object> orMap;
@ApiModelProperty(value = "模糊查询参数map 参数and连接")
public Map<String,Object> dimmap;
@ApiModelProperty(value = "模糊查询参数map 参数or连接")
public Map<String,Object> dimOrMap;
}
修改模板
@Data
@ApiModel(value = "es更新参数")
public class EsUpdate implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "索引")
public String indexName;
@ApiModelProperty(value = "文档id")
public String documentId;
@ApiModelProperty(value = "jsonObject")
public JSONObject json;
}
4.查询controller
@RestController
@RequestMapping("/Es")
@Api(tags = "ES测试",description = "ESController")
public class ESController {
@Autowired
private EsService esService;
@GetMapping("/createIndex")
@ApiOperation("创建索引")
public ResultVO createIndex(String indexName){
boolean status = esService.createIndex(indexName);
return new ResultVO<>(StatusCode.RESULT_SUCCESS,status);
}
@GetMapping("/indexExists")
@ApiOperation("判断索引是否存在")
public ResultVO indexExists(String indexName){
boolean status = esService.indexExists(indexName);
return new ResultVO<>(StatusCode.RESULT_SUCCESS,status);
}
@GetMapping("/deleteIndex")
@ApiOperation("测试删除索引")
public ResultVO deleteIndex(String indexName){
Boolean status = esService.deleteIndex(indexName);
if(status){
return new ResultVO<>(StatusCode.RESULT_SUCCESS,status);
}else {
return new ResultVO<>(999,"删除索引失败",status);
}
}
@GetMapping("/delData")
@ApiOperation("根据id删除文档")
public ResultVO delData(String indexName,String id){
boolean status = esService.delData(indexName, id);
if(status){
return new ResultVO<>(StatusCode.RESULT_SUCCESS,status);
}else {
return new ResultVO<>(999,"删除文档失败",status);
}
}
/**
{
"indexName":"zsq",
"jsonList":[
{
"areaId":"2222222",
"areaName": "2222222",
"date": 22222222,
"name": "2222222"
},
{
"areaId":"333333333",
"areaName": "3333333333",
"date": 3333333333,
"name": "3333333333"
},
{
"areaId":"444444444",
"areaName": "4444444444",
"date": 4444444444,
"name": "444444444"
}
]
}
*/
@PostMapping("/addList")
@ApiOperation("添加文档")
public ResultVO addList(@RequestBody ESInsert list){
String indexName = list.getIndexName();
List<JSONObject> jsonList = list.getJsonList();
boolean status = esService.addData(indexName, jsonList);
if(status){
return new ResultVO<>(StatusCode.RESULT_SUCCESS,status);
}else {
return new ResultVO<>(999,"操作失败!",status);
}
}
/**
{
"indexName":"zsq",
"documentId":"zVk8SXgB4FnvgKoT6mQq",
"json":{
"areaId":"111",
"areaName": "强无敌",
"date": 6666666666,
"name": "无敌"
}
}
*/
@PostMapping("/updateData")
@ApiOperation("更新文档") //更新要所有原始数据 ,先查再更新
public ResultVO updateData(@RequestBody EsUpdate esUpdate){
String indexName = esUpdate.getIndexName();
String documentId = esUpdate.getDocumentId();
JSONObject jsonObject = esUpdate.getJson();
boolean status = esService.updateData(indexName, documentId,jsonObject );
if(status){
return new ResultVO<>(StatusCode.RESULT_SUCCESS,status);
}else {
return new ResultVO<>(999,"操作失败!");
}
}
/**
* 请求格式
* {
* "highName":"name",
* "indexName":"zsq",
*
* "dimmap":{
* "areaName":"ang2",
* "name":"eng2"
* },
* "pageNum":1,
* "pageSize":20
* }
*/
@GetMapping("/queryData")
@ApiOperation("查询文档---按照id进行查询")
public ResultVO queryData(String indexName, String documentId) {
JSONObject jsonObject = esService.queryData(indexName, documentId);
return new ResultVO<>(StatusCode.RESULT_SUCCESS,jsonObject);
}
@PostMapping("/search")
@ApiOperation("查询")
public ResultVO search(@RequestBody ESParam esParam){
try {
String indexName = esParam.getIndexName();
Integer pageNum = esParam.getPageNum();
Integer pageSize = esParam.getPageSize();
String highName = esParam.getHighName();
Map<String, Object> map = esParam.getAndMap();
Map<String, Object> orMap = esParam.getOrMap();
Map<String, Object> dimmap = esParam.getDimmap();
Map<String, Object> dimOrMap = esParam.getDimOrMap();
Map<String, Object> search = esService.search(indexName, pageNum, pageSize, highName,map,dimmap,orMap,dimOrMap);
return new ResultVO<>(StatusCode.RESULT_SUCCESS,search);
}catch (Exception e){
e.printStackTrace();
throw new GlobalException(999,"查询错误");
}
}
}
5.service 实现类
@Service
@Slf4j
public class EsService {
@Autowired
RestHighLevelClient esClient;
//创建索引
public Boolean createIndex(String indexName) {
try {
//1.创建索引请求
CreateIndexRequest request = new CreateIndexRequest(indexName);
//2.客户端执行请求 indicessClient , 请求后获取响应
CreateIndexResponse createIndexResponse =
esClient.indices().create(request, RequestOptions.DEFAULT);
log.info("创建索引 createIndexResponse 的值为 : {}", createIndexResponse.toString());
return true;
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(999,"系统错误,创建索引失败");
}
}
/**
* 判断索引是否存在
*
* @param indexName
* @return
* @throws IOException
*/
public boolean indexExists(String indexName) {
try {
GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
boolean exists = esClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
return exists;
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(999,"系统错误,判断索引是否存在 失败");
}
}
public Boolean deleteIndex(String indexName) {
try {
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
AcknowledgedResponse delete = esClient.indices().delete(request, RequestOptions.DEFAULT);
log.info("删除索引{}, 返回结果为{}", indexName, delete.isAcknowledged());
return delete.isAcknowledged();
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(999,"系统错误,删除索引失败");
}
}
/**
* 删除文档
* @param indexName 索引(类似key)
*/
public boolean delData(String indexName) {
return delData(indexName, null);
}
/**
* 根据id删除文档
* @param indexName 索引(类似key)
* @param id id
*/
public boolean delData(String indexName, String id) {
try {
DeleteRequest request;
if (StringUtils.isEmpty(id)) {
request = new DeleteRequest(indexName);
} else {
request = new DeleteRequest(indexName, id);
}
DeleteResponse deleteResponse = esClient.delete(request, RequestOptions.DEFAULT);
RestStatus status = deleteResponse.status();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 批量新增文档
*
* @param indexName 索引(类似key)
* @param list 存储的数据实体类对象
*/
public boolean addData(String indexName, List<JSONObject> list) {
try {
BulkRequest request = new BulkRequest();
list.forEach(crowdMessageDTO -> {
String source = JSON.toJSONString(crowdMessageDTO);
request.add(new IndexRequest(indexName).source(source, XContentType.JSON));
});
BulkResponse bulk = esClient.bulk(request, RequestOptions.DEFAULT);
if (!bulk.hasFailures()) { //是否失败 ,返回false 代表成功
return true;
}else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(999,"系统错误,批量新增文档 失败");
}
}
/**
* 更新文档
*
* @param indexName 索引(类似key)
* @param documentId 文档id
* @param jsonObject 实体对象
*/
public boolean updateData(String indexName, String documentId, JSONObject jsonObject) {
try {
UpdateRequest updateRequest = new UpdateRequest(indexName, documentId).doc(JSON.toJSONString(jsonObject), XContentType.JSON);
// 执行更新
UpdateResponse update = esClient.update(updateRequest, RequestOptions.DEFAULT);
GetResult getResult = update.getGetResult();
int total = update.getShardInfo().getTotal();
if (total > 0) {
return true;
}else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(999,"系统错误,更新文档 失败");
}
}
/**
* 查询文档---按照id进行查询
*
* @param indexName 索引(类似key)
* @param documentId 文档id
*/
public JSONObject queryData(String indexName, String documentId) {
try {
GetRequest getRequest = new GetRequest(indexName, documentId);
// 查询结果
GetResponse documentFields = esClient.get(getRequest, RequestOptions.DEFAULT);
Map<String, DocumentField> fields = documentFields.getFields();
Map<String, Object> source = documentFields.getSource();// 索引的字段信息
return (JSONObject) JSONObject.toJSON(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 通用查询方法
* @param indexName 索引名称
* @param pageNum 开始页码
* @param pageSize 每页数据量
* @param highName 查询高亮字段名
* @param queryMap 精确查询参数map 参数and连接
* @param orMap 精确查询参数map 参数or连接
* @param dimap 模糊查询参数map 参数and连接
* @param dimOrMap 模糊查询参数map 参数or连接
* @return 查询结果
* @throws Exception 操作错误
*/
public Map<String, Object> search(String indexName, Integer pageNum, Integer pageSize,
String highName, Map<String, Object> queryMap, Map<String, Object> dimap
, Map<String, Object> orMap, Map<String, Object> dimOrMap) throws Exception {
SearchRequest searchRequest = new SearchRequest(indexName);
//构建搜索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = moreCondition(queryMap, dimap, orMap, dimOrMap);//构建多条件查询
sourceBuilder.query(boolQuery);
if (!StringUtils.isEmpty(highName)) {
highlightBuilder(sourceBuilder, highName);
}
limit(sourceBuilder, pageNum, pageSize); //构建分页
sourceBuilder.timeout(TimeValue.timeValueSeconds(60));
searchRequest.source(sourceBuilder);
return manageResult(pageNum, pageSize, highName, searchRequest);
}
/**
* 处理结果方法
* @param pageNum 开始页码
* @param pageSize 每页数据
* @param highName 高亮字段
* @param searchRequest 搜索请求
* @return map
* @throws IOException 操作异常
*/
public Map<String, Object> manageResult(Integer pageNum, Integer pageSize, String highName, SearchRequest searchRequest) throws IOException {
SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
JSONArray jsonArray = new JSONArray();
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); //原来的结果
if (!StringUtils.isEmpty(highName)) { //高亮存在,替换高亮
//解析高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField areaName = highlightFields.get(highName);
if (areaName != null) {
Text[] fragments = areaName.fragments();
String new_areaName = "";
for (Text text : fragments) {
new_areaName += text;
}
sourceAsMap.put(highName, new_areaName); //高亮字段替换之前字段
}
}
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(sourceAsMap));
jsonArray.add(jsonObject);
}
int total = (int) hits.getTotalHits().value; //总数
Map<String, Object> map = new HashMap<String, Object>();
map.put("data", jsonArray);
map.put("pageNum", pageNum);
map.put("pageSize", pageSize);
map.put("total", total);
map.put("pages", total == 0 ? 0 : (total % pageSize == 0 ? total / pageSize : (total / pageSize) + 1));
return map;
}
/**
* 构建高亮字段
* @param sourceBuilder 条件构造器
* @param name 高亮字段
*/
public void highlightBuilder(SearchSourceBuilder sourceBuilder, String name) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field(name); //高亮字段
highlightBuilder.requireFieldMatch(false); //多个高亮显示
highlightBuilder.preTags("<span style='color:red'>"); //标签前缀
highlightBuilder.postTags("</span>");//标签后缀
sourceBuilder.highlighter(highlightBuilder);
}
/**
* 构建分页
* @param sourceBuilder 条件构造器
* @param pageNum 页码
* @param pageSize 每页数据量
*/
public void limit(SearchSourceBuilder sourceBuilder, Integer pageNum, Integer pageSize) {
if (sourceBuilder != null && !StringUtils.isEmpty(pageNum) && !StringUtils.isEmpty(pageSize)) {
//分页
sourceBuilder.from((pageNum - 1) * pageSize); //开始位置
sourceBuilder.size(pageSize); //结束
}
}
/**
* 多条件查询
* @param map 精确查询参数map 参数and连接
* @param orMap 精确查询参数map 参数or连接
* @param dimap 模糊查询参数map 参数and连接
* @param dimOrMap 模糊查询参数map 参数or连接
* @return 多条件构造器
*/
public BoolQueryBuilder moreCondition(Map<String, Object> map, Map<String, Object> dimap
, Map<String, Object> orMap, Map<String, Object> dimOrMap) {
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//多条件设置 参数and连接
//matchPhraseQuery是没有用分词起,matchQuery会使用分词器,将我们输入的值进行分割,如:“java动态”会分割成:“java”,“动态”
if (!CollectionUtils.isEmpty(map)) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(entry.getKey(), entry.getValue());
boolQueryBuilder.must(matchQueryBuilder);
}
}
//精确查询参数map 参数or连接
if (!CollectionUtils.isEmpty(orMap)) {
for (Map.Entry<String, Object> entry : orMap.entrySet()) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(entry.getKey(), entry.getValue());
boolQueryBuilder.should(matchQueryBuilder);
}
}
//模糊查询 参数and连接
if (!CollectionUtils.isEmpty(dimap)) {
for (Map.Entry<String, Object> entry : dimap.entrySet()) {
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(entry.getKey(), "*" + entry.getValue() + "*");
boolQueryBuilder.must(wildcardQueryBuilder);
}
}
//模糊查询 参数or连接
if (!CollectionUtils.isEmpty(dimOrMap)) {
for (Map.Entry<String, Object> entry : dimOrMap.entrySet()) {
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(entry.getKey(), "*" + entry.getValue() + "*");
boolQueryBuilder.should(wildcardQueryBuilder);
}
}
return boolQueryBuilder;
}
/***********************************************************************业务类通用方法**********************************************************/
/**
* 实体类转Map
*
* @param object
* @return
*/
public static Map<String, Object> entityToMap(Object object) {
Map<String, Object> map = new HashMap();
for (Field field : object.getClass().getDeclaredFields()) {
try {
boolean flag = field.isAccessible();
field.setAccessible(true);
Object o = field.get(object);
map.put(field.getName(), o);
field.setAccessible(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
return map;
}
}