Spring boot集成elasticsearch7.15

Spring boot集成elasticsearch7.15

个人编写整合仅供参考

出事概不负责!

此次整合的ES使用了ik分词器跟数据库配置同义词,ik分词器跟同义词可以查看本人其他文章有安装步骤

程序可看下面的垃圾代码。

1.修改pom文件

<project>    <dependencies>            <dependency>            <groupId>org.elasticsearch.client</groupId>            <artifactId>elasticsearch-rest-high-level-client</artifactId>            <version>${elastic.version}</version>        </dependency>                <dependency>            <groupId>org.elasticsearch.client</groupId>            <artifactId>elasticsearch-rest-client</artifactId>            <version>${elastic.version}</version>        </dependency>                <dependency>            <groupId>org.elasticsearch</groupId>            <artifactId>elasticsearch</artifactId>            <version>${elastic.version}</version>        </dependency>                <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-databind</artifactId>            <version>2.11.1</version>        </dependency>            </dependencies>    <properties>        <elastic.version>7.15.0</elastic.version>    </properties>    </project>

2.Controller

package com.xxx.web.controller.es;

import com.xxx.business.es.domain.vo.SearchVo;
import com.xxx.business.es.domain.vo.TitleVo;
import com.xxx.business.es.service.ContentService;
import com.xxx.business.keywordSubscription.domain.BKeywordSubscription;
import com.xxx.business.keywordSubscription.service.IBKeywordSubscriptionService;
import com.xxx.common.constant.HttpStatus;
import com.xxx.common.core.controller.BaseController;
import com.xxx.common.core.domain.AjaxResult;
import com.xxx.common.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@RestController
@RequestMapping("/business/es")
public class ContentController extends BaseController {

@Autowired
private ContentService contentService;

@Autowired
private IBKeywordSubscriptionService ibKeywordSubscriptionService;

//同步所有用的
@PutMapping("/parse")
public AjaxResult parse() throws IOException {
return AjaxResult.success(contentService.parseContent());
}

//同步单个用的
@PutMapping("/parseOne/{ids}")
public AjaxResult parseOne(@PathVariable String[] ids) throws IOException {
return AjaxResult.success(contentService.parseContent(ids));
}

@GetMapping("/search")
public TableDataInfo search(SearchVo searchVo) throws IOException {
Map map = contentService.searchPageForHighlight(searchVo);
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
List<TitleVo> listAll = (List<TitleVo>) map.get("listAll");
rspData.setRows(listAll);
Integer total = (Integer) map.get("total");
rspData.setTotal(total);
return rspData;
}
}

3.service

package com.xxx.business.es.service;


import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.xxx.business.es.domain.vo.SearchVo;
import com.xxx.business.es.domain.vo.TitleVo;
import com.xxx.business.title.mapper.BTitleMapper;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
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.CreateIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
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.ObjectUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.ruoyi.business.es.utils.CommonConstant.INDEX;
import static com.ruoyi.business.es.utils.CommonConstant.INDEX_O;


/**
* 业务编写
*/
@Service
public class ContentService {

@Autowired
private RestHighLevelClient restHighLevelClient;
@Autowired
private BTitleMapper bTitleMapper;

// 1. 解析数据放入到es索引当中
public Boolean parseContent() throws IOException {
//判断是否存在
GetIndexRequest getIndexRequest = new GetIndexRequest();
getIndexRequest.indices(INDEX);
Boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
//如果存在就删除
if (exists) {
restHighLevelClient.indices().delete(new DeleteIndexRequest(INDEX), RequestOptions.DEFAULT);
}
String mappings = "{\n" +
" \"properties\": {\n" +
" \"name\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_syno_max\",\n" +
" \"search_analyzer\": \"ik_syno\"\n" +
" },\n" +
" \"title\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"search_analyzer\": \"ik_smart\"\n" +
" }\n" +
" }\n" +
" }";
String settings = "{\n" +
" \"number_of_shards\": 1,\n" +
" \"number_of_replicas\": 0,\n" +
" \"index\": {\n" +
" \"analysis\": {\n" +
" \"filter\": {\n" +
" \"mysql_synonym\": {\n" +
" \"type\": \"dynamic_synonym\",\n" +
" \"synonyms_path\": \"fromMySql\",\n" +
" \"interval\": 30\n" +
" }\n" +
" },\n" +
" \"analyzer\": {\n" +
" \"ik_syno\": {\n" +
" \"type\": \"custom\",\n" +
" \"tokenizer\": \"ik_smart\",\n" +
" \"filter\": [\n" +
" \"mysql_synonym\"\n" +
" ]\n" +
" },\n" +
" \"ik_syno_max\": {\n" +
" \"type\": \"custom\",\n" +
" \"tokenizer\": \"ik_max_word\",\n" +
" \"filter\": [\n" +
" \"mysql_synonym\"\n" +
" ]\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }";
try {
CreateIndexRequest request = new CreateIndexRequest(INDEX);
request.settings(settings, XContentType.JSON);
request.mapping(mappings, XContentType.JSON);
//创建索引
restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
//下面这个list是查询标题的 然后添加到es里
List<TitleVo> contents = bTitleMapper.selectTitleList();
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("200m");
for (int i = 0; i < contents.size(); i++) {
bulkRequest.add(new IndexRequest(INDEX, "_doc", i + "").source(JSON.toJSONString(contents.get(i)), XContentType.JSON));
}

BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
return !bulk.hasFailures();
}

public Boolean parseContent(String[] ids) throws IOException {
//下面这个list是查询标题的 然后添加到es里
List<TitleVo> contents = bTitleMapper.selectTitleListById(ids);
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("200m");
for (int i = 0; i < contents.size(); i++) {
TitleVo titleVo = contents.get(i);
String id1 = titleVo.getId();
GetIndexRequest getIndexRequest = new GetIndexRequest();
getIndexRequest.indices(INDEX);
Boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
SearchRequest searchRequest = null;
if (exists) {
searchRequest = new SearchRequest(INDEX);
} else {
searchRequest = new SearchRequest(INDEX_O);
}
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
sourceBuilder.size(10000);
boolQueryBuilder.must(new MatchQueryBuilder("id", id1));
sourceBuilder.query(boolQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = searchResponse.getHits().getHits();
if (hits.length == 0) {
SearchSourceBuilder sourceBuilder1 = new SearchSourceBuilder();
SearchRequest searchRequest1 = new SearchRequest(INDEX);
sourceBuilder1.size(10000);
sourceBuilder1.searchAfter();
searchRequest1.source(sourceBuilder1);
SearchResponse searchResponse1 = restHighLevelClient.search(searchRequest1, RequestOptions.DEFAULT);
int length = searchResponse1.getHits().getHits().length;
bulkRequest.add(new IndexRequest(INDEX, "_doc", length + 1 + "").source(JSON.toJSONString(contents.get(i)), XContentType.JSON));
} else {
String id = hits[0].getId();
bulkRequest.add(new IndexRequest(INDEX, "_doc", id + "").source(JSON.toJSONString(contents.get(i)), XContentType.JSON));
}
}

BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
return !bulk.hasFailures();
}

// 2. 查询这些数据实现搜索功能
public Map searchPageForHighlight(SearchVo searchVo) throws IOException {
String keywords = searchVo.getKeywords();
String dataSourceType = searchVo.getDataSourceType();
String id = searchVo.getId();
int pageNo = searchVo.getPageNum();
int pageSize = searchVo.getPageSize();
if (pageNo <= 1) {
pageNo = 0;
}
if (pageNo != 0) {
pageNo = pageNo * pageSize - pageSize;
}
List<TitleVo> listAll = new ArrayList<>();
int total = 0;
if (!ObjectUtils.isEmpty(dataSourceType) && !dataSourceType.equals("001")) {
// 条件搜索
GetIndexRequest getIndexRequest = new GetIndexRequest();
getIndexRequest.indices(INDEX);
Boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
SearchRequest searchRequest = null;
SearchRequest searchRequest1 = null;
if (exists) {
searchRequest = new SearchRequest(INDEX);
searchRequest1 = new SearchRequest(INDEX);
} else {
searchRequest = new SearchRequest(INDEX_O);
searchRequest1 = new SearchRequest(INDEX_O);
}
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
SearchSourceBuilder sourceBuilder1 = new SearchSourceBuilder();
sourceBuilder1.size(10000);
// 分页
if (pageSize != 0) {
sourceBuilder.from(pageNo);
sourceBuilder.size(pageSize);
}
BoolQueryBuilder boolQueryBuilder5 = new BoolQueryBuilder();
boolean keywordsEmpty = ObjectUtils.isEmpty(keywords);
boolean idEmpty = ObjectUtils.isEmpty(id);
if (exists) {
if (!idEmpty) {
boolQueryBuilder5.must(new MatchQueryBuilder("id", id));
// 当前下面这个相当于mysql中where条件 a=8 and (b=3 or b=4)
boolQueryBuilder5.must(QueryBuilders.boolQuery().should(QueryBuilders.wildcardQuery("ancestors", "*" + dataSourceType + "*")).should(new MatchQueryBuilder("dataSourceType", dataSourceType)));
sourceBuilder.query(boolQueryBuilder5);
sourceBuilder1.query(boolQueryBuilder5);
} else if (!keywordsEmpty) {
boolQueryBuilder5.must(new MatchQueryBuilder("title", keywords));
// 当前下面这个相当于mysql中where条件 a=8 and (b=3 or b=4)
boolQueryBuilder5.must(QueryBuilders.boolQuery().should(QueryBuilders.wildcardQuery("ancestors", "*" + dataSourceType + "*")).should(new MatchQueryBuilder("dataSourceType", dataSourceType)));
sourceBuilder.query(boolQueryBuilder5);
sourceBuilder1.query(boolQueryBuilder5);
} else {
// 当前下面这个相当于mysql中where条件 a=8 and (b=3 or b=4)
boolQueryBuilder5.must(QueryBuilders.boolQuery().should(QueryBuilders.wildcardQuery("ancestors", "*" + dataSourceType + "*")).should(new MatchQueryBuilder("dataSourceType", dataSourceType)));
sourceBuilder.query(boolQueryBuilder5);
sourceBuilder1.query(boolQueryBuilder5);
}
}
// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.requireFieldMatch(false); // 多个高亮显示
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
sourceBuilder.highlighter(highlightBuilder);
sourceBuilder.searchAfter();
if (exists) {
if (!idEmpty) {
sourceBuilder.sort("_score", SortOrder.DESC); //排序
sourceBuilder.sort("dataSourceType", SortOrder.DESC); //排序
} else if (!keywordsEmpty) {
sourceBuilder.sort("_score", SortOrder.DESC); //排序
sourceBuilder.sort("dataSourceType", SortOrder.DESC); //排序
} else {
sourceBuilder.sort("dataSourceType", SortOrder.DESC); //排序
}
}
// 执行搜索
searchRequest.source(sourceBuilder);
searchRequest1.source(sourceBuilder1);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchResponse searchResponse1 = restHighLevelClient.search(searchRequest1, RequestOptions.DEFAULT);
// 解析结果
for (SearchHit documentField : searchResponse.getHits().getHits()) {
Map<String, HighlightField> highlightFields = documentField.getHighlightFields();
HighlightField title = highlightFields.get("title");
Map<String, Object> sourceAsMap = documentField.getSourceAsMap(); // 原来的结果
// 解析高亮的字段, 将原来的字段换为我们高亮的字段即可!
if (title != null) {
Text[] fragments = title.fragments();
String n_title = "";
for (Text text : fragments) {
n_title += text;
}
sourceAsMap.put("title", n_title);
}
listAll.add(JSONUtil.toBean(JSONUtil.toJsonStr(sourceAsMap), TitleVo.class));
}
int length = searchResponse1.getHits().getHits().length;
total += length;
} else {
// 条件搜索
GetIndexRequest getIndexRequest = new GetIndexRequest();
getIndexRequest.indices(INDEX);
Boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
SearchRequest searchRequest = null;
SearchRequest searchRequest1 = null;
if (exists) {
searchRequest = new SearchRequest(INDEX);
searchRequest1 = new SearchRequest(INDEX);
} else {
searchRequest = new SearchRequest(INDEX_O);
searchRequest1 = new SearchRequest(INDEX_O);
}
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
SearchSourceBuilder sourceBuilder1 = new SearchSourceBuilder();
sourceBuilder1.size(10000);
// 分页
if (pageSize != 0) {
sourceBuilder.from(pageNo);
sourceBuilder.size(pageSize);
}
BoolQueryBuilder boolQueryBuilder5 = new BoolQueryBuilder();
boolean keywordsEmpty = ObjectUtils.isEmpty(keywords);
boolean idEmpty = ObjectUtils.isEmpty(id);
if (!idEmpty && exists) {
boolQueryBuilder5.must(new MatchQueryBuilder("id", id));
sourceBuilder.query(boolQueryBuilder5);

sourceBuilder1.query(boolQueryBuilder5);

} else if (!keywordsEmpty && exists) {
boolQueryBuilder5.must(new MatchQueryBuilder("title", keywords));
sourceBuilder.query(boolQueryBuilder5);
sourceBuilder1.query(boolQueryBuilder5);
} else {
sourceBuilder.query(QueryBuilders.matchAllQuery());
sourceBuilder1.query(QueryBuilders.matchAllQuery());
}
// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.requireFieldMatch(false); // 多个高亮显示!
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
sourceBuilder.highlighter(highlightBuilder);
sourceBuilder.searchAfter();
sourceBuilder1.searchAfter();
if (exists) {
if (!idEmpty) {
sourceBuilder.sort("_score", SortOrder.DESC); //排序
sourceBuilder.sort("dataSourceType", SortOrder.DESC); //排序
} else if (!keywordsEmpty) {
sourceBuilder.sort("_score", SortOrder.DESC); //排序
sourceBuilder.sort("dataSourceType", SortOrder.DESC); //排序
} else {
sourceBuilder.sort("dataSourceType", SortOrder.DESC); //排序
}
}
// 执行搜索
searchRequest.source(sourceBuilder);
searchRequest1.source(sourceBuilder1);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchResponse searchResponse1 = restHighLevelClient.search(searchRequest1, RequestOptions.DEFAULT);
// 解析结果
for (SearchHit documentField : searchResponse.getHits().getHits()) {
Map<String, HighlightField> highlightFields = documentField.getHighlightFields();
HighlightField title = highlightFields.get("title");
Map<String, Object> sourceAsMap = documentField.getSourceAsMap(); // 原来的结果
// 解析高亮的字段, 将原来的字段换为我们高亮的字段即可!
if (title != null) {
Text[] fragments = title.fragments();
String n_title = "";
for (Text text : fragments) {
n_title += text;
}
sourceAsMap.put("title", n_title);
}
listAll.add(JSONUtil.toBean(JSONUtil.toJsonStr(sourceAsMap), TitleVo.class));
}
total += searchResponse1.getHits().getHits().length;
}

Map map = new HashMap();
map.put("listAll", listAll);
map.put("total", total);
return map;
}
}

4.utils

package com.xxx.business.es.utils;
public class CommonConstant {
//es的index不能有大写 必须为小写
public static final String INDEX = "buuindex";
public static final String INDEX_O = "buuindex1";
}

5.config

package com.xxx.web.core.config;import org.apache.http.HttpHost;import org.apache.http.auth.AuthScope;import org.apache.http.auth.UsernamePasswordCredentials;import org.apache.http.client.CredentialsProvider;import org.apache.http.impl.client.BasicCredentialsProvider;import org.elasticsearch.client.RestClient;import org.elasticsearch.client.RestClientBuilder;import org.elasticsearch.client.RestHighLevelClient;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class ElasticSearchClientConfig {    public static RestHighLevelClient client = null;    /**     * 是否使用密码     */    @Value("${elasticSearch.enabled}")    private boolean enabled;    /**     * 访问方式     */    @Value("${elasticSearch.scheme}")    private String scheme;    /**     * 地址     */    @Value("${elasticSearch.hostname}")    private String hostname;    /**     * 端口     */    @Value("${elasticSearch.port}")    private Integer port;    /**     * 登录账户     */    @Value("${elasticSearch.userName}")    private String userName;    /**     * 登录密码     */    @Value("${elasticSearch.password}")    private String password;    @Bean    public RestHighLevelClient restHighLevelClient() {        if (enabled) {            //需要密码进行访问            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));            RestClientBuilder restClientBuilder = RestClient.builder(                            new HttpHost(hostname, port, scheme)                    )                    .setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider));            client = new RestHighLevelClient(restClientBuilder);        } else {            //不需要密码就可以访问            client = new RestHighLevelClient(                    RestClient.builder(                            new HttpHost(hostname, port, scheme)                    )            );        }        return client;    }}

6,application.yml

  # es配置elasticSearch:  # 是否需要密码访问  enabled: true  # 访问方式  scheme: http  # 地址  hostname: 127.0.0.1  #端口  port: 9200  #用户名  userName: elastic  #密码  password: XXXXXX

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部