springboot工程中使用es实现搜索功能

ElasticSearch是一个基于Lucene的开源的、分布式实时搜索和分析引擎。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。

上一节我们以及安装好了elasticsearch以及kibana、IK分词器

现在让我们看看如何在springboot工程中使用吧。

安装依赖

我们使用的是7.x,注意7.x和8.x的差别较大,初学者可以先从7.x入手。

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.12.1</version>
        </dependency>

es配置

yml文件配置

elasticsearch:
  hostlist: 你的es服务ip #多个结点中间用逗号分隔
  article:
    index: article
    source_fields: id,title,content,summary,thumbnail,categoryId,isTop,status,viewCount,isComment,createTime
@Configuration
public class ElasticsearchConfig {
    @Value("${elasticsearch.hostlist}")
    private String hostlist;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        //解析hostlist配置信息
        String[] split = hostlist.split(",");
        //创建HttpHost数组,其中存放es主机和端口的配置信息
        HttpHost[] httpHostArray = new HttpHost[split.length];
        for (int i = 0; i < split.length; i++) {
            String item = split[i];
            httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
        }
        //创建RestHighLevelClient客户端
        return new RestHighLevelClient(RestClient.builder(httpHostArray));
    }
}

索引

定义service接口

public interface IndexService {
    /**
     * 添加文章索引
     * @param
     * @return
     */
    public Boolean addArticleIndex(String indexName, String id, Object object);
}

实现service接口

@Service
@Slf4j
public class IndexServiceImpl implements IndexService {

    @Resource
    RestHighLevelClient client;


    @Override
    public Boolean addArticleIndex(String indexName, String id, Object object) {
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = sdf.format(((Article) object).getCreateTime());

        // 将格式化后的日期字符串替换 JSON 字符串中的 createTime 字段
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(object));
        jsonObject.put("createTime", dateString);
        String jsonString = jsonObject.toJSONString();
//        String jsonString = JSON.toJSONString(object);
        IndexRequest indexRequest = new IndexRequest(indexName).id(id);
        //指定索引文档内容
        indexRequest.source(jsonString, XContentType.JSON);
        //索引响应对象
        IndexResponse indexResponse = null;
        try {
            indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("添加索引出错:{}", e.getMessage());
            e.printStackTrace();
            ZhiWenPlusException.cast("添加索引出错");
        }
        String name = indexResponse.getResult().name();
        System.out.println(name);
        return name.equalsIgnoreCase("created") || name.equalsIgnoreCase("updated");
    }
}

创建索引接口

@RestController
@RequestMapping("search/index")
public class ArticleIndexController {

    @Value("${elasticsearch.article.index}")
    private String courseIndexStore;

    @Resource
    private IndexService indexService;

    @ApiOperation(value = "添加文章索引")
    @PostMapping("/article")
    public Boolean addIndex(@RequestBody Article article) {
        Long id = article.getId();
        if (id == null) {
            ZhiWenPlusException.cast("文章id为空");
        }
        Boolean result = indexService.addArticleIndex(courseIndexStore, String.valueOf(id), article);
        if (!result) {
            ZhiWenPlusException.cast("添加课程索引失败");
        }
        return result;
    }
}

搜索

根据关键字搜索文章信息,搜索方式为全文检索,关键字需要匹配文章的标题、简介,并且高亮显示。

定义service接口

public interface ArticleSearchService {
    /**
     * 搜索文章信息
     * @param pageNo
     * @param pageSize
     * @param keyWords
     * @return
     */
    ResponseResult queryArticleIndex(Long pageNo, Long pageSize, String keyWords);
}

实现service接口

@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {

    @Value("${elasticsearch.article.index}")
    private String courseIndexStore;
    @Value("${elasticsearch.article.source_fields}")
    private String sourceFields;

    @Resource
    RestHighLevelClient client;


    @Override
    public ResponseResult queryArticleIndex(Long pageNo, Long pageSize,String keyWords) {
        //设置索引
        SearchRequest searchRequest = new SearchRequest(courseIndexStore);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //source源字段过虑
        String[] sourceFieldsArray = sourceFields.split(",");
        searchSourceBuilder.fetchSource(sourceFieldsArray, new String[]{});

        if (StringUtils.isNotEmpty(keyWords)) {
            //匹配关键字
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyWords, "title", "summary");
            //设置匹配占比
            multiMatchQueryBuilder.minimumShouldMatch("70%");
            //提升另个字段的Boost值
            multiMatchQueryBuilder.field("title", 10);
            boolQueryBuilder.must(multiMatchQueryBuilder);
        }

        int start = (int) ((pageNo - 1) * pageSize);
        searchSourceBuilder.from(start);
        searchSourceBuilder.size(Math.toIntExact(pageSize));
        //布尔查询
        searchSourceBuilder.query(boolQueryBuilder);
        //高亮设置
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font class='eslight'>");
        highlightBuilder.postTags("</font>");
        //设置高亮字段
        highlightBuilder.fields().add(new HighlightBuilder.Field("title"));
        searchSourceBuilder.highlighter(highlightBuilder);
        //请求搜索
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("课程搜索异常:{}", e.getMessage());
//            return new SearchPageResultDto<CourseIndex>(new ArrayList(), 0, 0, 0);
            ZhiWenPlusException.cast("课程搜索异常");
        }

        //结果集处理
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        //记录总数
        TotalHits totalHits = hits.getTotalHits();
        //数据列表
        List<Article> list = new ArrayList<>();

        for (SearchHit hit : searchHits) {

            String sourceAsString = hit.getSourceAsString();
            Article article = JSON.parseObject(sourceAsString, Article.class);

            //取出source
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();

            //课程id
            Long id = article.getId();
            //取出名称
            String title = article.getTitle();
            //取出高亮字段内容
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields != null) {
                HighlightField nameField = highlightFields.get("title");
                if (nameField != null) {
                    Text[] fragments = nameField.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for (Text str : fragments) {
                        stringBuffer.append(str.string());
                    }
                    title = stringBuffer.toString();

                }
            }
            article.setId(id);
            article.setTitle(title);

            list.add(article);

        }

        return new ResponseResult().ok(list);
    }
}

创建搜索接口

@RestController
@RequestMapping("search/article")
public class ArticleSearchController {

    @Resource
    private ArticleSearchService articleSearchService;

    @GetMapping("/list")
    public ResponseResult searchArticle(Long pageNum, Long pageSize,String keywords) {
        ResponseResult result = articleSearchService.queryArticleIndex(pageNum, pageSize, keywords);
        return result;
    }
}

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot使用ElasticSearch需要借助Spring Data Elasticsearch模块,该模块提供了一系列的API,方便我们对ElasticSearch进行操作。 以下是在Spring Boot使用ElasticSearch的简单步骤: 1.添加依赖 在pom.xml文件添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 2.配置ElasticSearch 在application.properties文件添加以下配置: ``` spring.data.elasticsearch.cluster-nodes=localhost:9300 spring.data.elasticsearch.cluster-name=my-application ``` 3.创建实体类 在使用Spring Data Elasticsearch进行操作时,需要先定义实体类,该类需要使用@Document注解进行标注,同时需要使用@Id注解指定主键字段。 例如: ``` @Document(indexName = "my_index", type = "my_type") public class MyDocument { @Id private String id; private String name; private String description; // getter / setter } ``` 4.创建Repository 使用Spring Data Elasticsearch提供的ElasticsearchRepository接口,继承该接口并传入实体类和主键类型,即可直接使用CRUD操作。 例如: ``` public interface MyDocumentRepository extends ElasticsearchRepository<MyDocument, String> { } ``` 5.使用Repository进行操作 在需要对Elasticsearch进行操作的地方,使用@Autowired注解注入MyDocumentRepository即可。 例如: ``` @Autowired private MyDocumentRepository myDocumentRepository; public void test() { MyDocument myDocument = new MyDocument(); myDocument.setName("test"); myDocument.setDescription("test description"); myDocumentRepository.save(myDocument); } ``` 以上就是在Spring Boot使用ElasticSearch的简单步骤。需要注意的是,以上只是最基础的使用方法,实际使用还需要根据具体需求进行配置和操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值