其他分享
首页 > 其他分享> > 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;

@Configuration
public 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

 

标签:INDEX,Spring,Boot,sourceBuilder,new,elasticsearch7.15,elasticsearch,org,import
来源: https://www.cnblogs.com/shiheng01/p/16288685.html