SpringBoot整合ElasticSearch

7 SpringBoot整合ElasticSearch

7.1 导入依赖
xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
7.2 写yml
yaml 复制代码
spring:
  elasticsearch:
    rest:
      uris: 127.0.0.1:9200 #地址
7.3 实体映射
java 复制代码
package com.cxs.elasticsearch.entity;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.time.LocalDateTime;

/*
 * @Author:cxs
 * @Motto:放下杂念,只为迎接明天更好的自己
 * */
@Data
@Document(indexName = "good_item_index")
public class GoodItem {
    @Id
    private Long id;
    @Field(type = FieldType.Long)
    private Long spu;
    @Field(type = FieldType.Long)
    private Long sku;
    @Field(type = FieldType.Text)
    private String title;
    @Field(type = FieldType.Long)
    private Long price;
    @Field(type = FieldType.Text)
    private String pic;
    @Field(type = FieldType.Text)
    private String url;
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDateTime createTime;
    @Field(type = FieldType.Date, format = DateFormat.date)
    private LocalDateTime updateTime;
}
7.4 Dao
java 复制代码
package com.cxs.elasticsearch.dao;

import com.cxs.elasticsearch.entity.GoodItem;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

/*
 * @Author:cxs
 * @Motto:放下杂念,只为迎接明天更好的自己
 * */
@Repository
public interface GoodItenDao extends ElasticsearchRepository<GoodItem, Long> {

}
7.5 Service
java 复制代码
package com.cxs.service.impl;

import com.cxs.elasticsearch.dao.GoodItenDao;
import com.cxs.elasticsearch.entity.GoodItem;
import com.cxs.service.GoodService;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*
 * @Author:cxs
 * @Motto:放下杂念,只为迎接明天更好的自己
 * */
@Service
public class GoodServiceImpl implements GoodService {
    @Autowired
    private GoodItenDao goodItenDao;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public Boolean save(GoodItem goodItem) {
        GoodItem save = goodItenDao.save(goodItem);
        System.out.println(save);
        return save != null;
    }

    @Override
    public List<GoodItem> findAll() {
        Iterable<GoodItem> all = goodItenDao.findAll();
        List<GoodItem> list = new ArrayList<>();
           all.forEach(a -> {
               list.add(a);
           });
        return list;
    }

    @Override
    public List<GoodItem> search(GoodItem goodItem) {
        Iterable<GoodItem> search = goodItenDao.search(QueryBuilders.termsQuery("url", goodItem.getUrl()));
        List<GoodItem> list = new ArrayList<>();
        search.forEach(a -> {
            list.add(a);
        });
        return list;
    }

    @Override
    public List<GoodItem> query(GoodItem goodItem) {
        List<GoodItem> list = new ArrayList<>();
        GoodItem item = elasticsearchRestTemplate.get("", GoodItem.class);
        return list;
    }
}
7.6 测试
java 复制代码
//  ... 测试省略
7.7 复杂查询

ElasticsearchRepository中许多方法已经被弃用,实现复杂操作就需要自己实现,注入

ElasticsearchRestTemplate完成复杂操作,注意,原先的ElasticsearchTemplate已经弃用

7.7.1 使用ElasticsearchRestTemplate完成Match查询
java 复制代码
// 匹配url is https://item.jd.com/100016034400.html
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("url", "https://item.jd.com/100016034400.html");
NativeSearchQuery query = new NativeSearchQuery(matchQueryBuilder);
SearchHits<GoodItem> search = elasticsearchRestTemplate.search(query, GoodItem.class);
List<SearchHit<GoodItem>> hits = search.getSearchHits();
List<GoodItem> list = new ArrayList<>();
// 总数
long totalHits = search.getTotalHits();
for (SearchHit<GoodItem> hit : hits) {
    GoodItem content = hit.getContent();
    list.add(content);
}
System.out.println(list);
7.7.2 使用ElasticsearchRestTemplate完成Bool查询
java 复制代码
    @Test
    void contextLoads1() {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("url", "https://item.jd.com/100016034400.html");
        TermQueryBuilder termQuery = QueryBuilders.termQuery("url", "https://item.jd.com/100016034400.html");
        boolQueryBuilder.should(matchQuery).should(termQuery);
        NativeSearchQuery query = new NativeSearchQuery(boolQueryBuilder);
        SearchHits<GoodItem> search = elasticsearchRestTemplate.search(query, GoodItem.class);
        System.out.println(search);
        List<SearchHit<GoodItem>> hits = search.getSearchHits();
        List<GoodItem> list = new ArrayList<>();
        long totalHits = search.getTotalHits();
        for (SearchHit<GoodItem> hit : hits) {
            GoodItem content = hit.getContent();
            list.add(content);
        }
        System.out.println(list);
    }
7.7.3 Es批量操作,存在即修改,不存在即插入
java 复制代码
    @Test
    void contextLoads1() {
        BulkRequest bulkRequest = new BulkRequest();
        for (FinancialDoc document : documents) {
            document.setProdId(getProductId(document));
            document.setRefreshTime(LocalDateTime.now());
            IndexRequest indexRequest = new IndexRequest(getIndex())
                    .id(document.getProdId())
                    .source(JSON.toJSONString(document), XContentType.JSON);
            UpdateRequest request = new UpdateRequest(getIndex(), document.getProdId())
                    .doc(JSON.toJSONString(document), XContentType.JSON).upsert(indexRequest);
            bulkRequest.add(request);
        }
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        return bulkResponse.status().equals(RestStatus.OK);
    }
7.7.4 Es全量查询文档,总数大于10000条

使用scroll,每次1000条查询,可自行调整

java 复制代码
public List<StockDoc> selectAllList() throws IOException {
        SearchRequest request = new SearchRequest();
        request.indices(getIndex());
        List<StockDoc> result = new ArrayList<>();
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(1000).query(QueryBuilders.matchAllQuery());
        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
        request.scroll(scroll)
                .source(builder);
        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);
        String scrollId = searchResponse.getScrollId();
        SearchHit[] searchHits = searchResponse.getHits().getHits();
        while (searchHits != null && searchHits.length > 0) {
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                result.add(JSON.parseObject(hit.getSourceAsString(), StockDoc.class));
            }
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            scrollRequest.scroll(scroll);
            searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
            searchHits = searchResponse.getHits().getHits();
        }
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        clearScrollRequest.addScrollId(scrollId);
        client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
        return result;
    }
7.7.5 复杂搜索-权重,优先级排序
java 复制代码
private void globalSearchConditionHandler(SearchDTO dto, SearchSourceBuilder builder) {
        // 封装分页数据
        builder.from((dto.getPageNum() - 1) * dto.getPageSize());
        builder.size(dto.getPageSize());
        Script script =
                new Script("if (doc['code.keyword'].value == '" + dto.getKeyword() + "') {return doc['code.keyword'].value.length();} else {if(doc['codeType.keyword'].value == '4353' || doc['codeType.keyword'].value == '4609') {return 1;} else {return 0;}}");
        Script codeTypeScript =
                new Script("return Integer.parseInt(doc['codeType.keyword'].value)");
        SortBuilder sortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);
        SortBuilder codeTypeScriptBuild = SortBuilders.scriptSort(codeTypeScript, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.ASC);
        SortBuilder scoreBuild = SortBuilders.fieldSort("_score").order(SortOrder.DESC);
        SortBuilder codeBuild = SortBuilders.fieldSort("code.keyword").order(SortOrder.ASC);
        builder.sort(scoreBuild);
        builder.sort(sortBuilder);
        builder.sort(codeTypeScriptBuild);
        builder.sort(codeBuild);
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(dto.getKeyword())) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.should(QueryBuilders.wildcardQuery("code.keyword", swapLeftKey(dto.getKeyword())).boost(100.0f))
                    .should(QueryBuilders.wildcardQuery("code.keyword", swapKey(dto.getKeyword())).boost(90.0f))
                    .should(QueryBuilders.wildcardQuery("codeName.keyword", swapLeftKey(dto.getKeyword())).boost(10.0f))
                    .should(QueryBuilders.wildcardQuery("codeName.keyword", swapKey(dto.getKeyword())).boost(9.5f))
                    .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapLeftKey(dto.getKeyword())).boost(9.0f))
                    .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapLeftKey(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(9.0f))
                    .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapLeftKey(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(9.0f))
                    .should(QueryBuilders.regexpQuery("pinYin.keyword", regexStr(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(8.0f))
                    .should(QueryBuilders.regexpQuery("pinYin.keyword", regexStr(dto.getKeyword().toLowerCase(Locale.ROOT))).boost(8.0f))
                    .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapKey(dto.getKeyword())).boost(7.0f))
                    .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapKey(dto.getKeyword().toUpperCase(Locale.ROOT))).boost(7.0f))
                    .should(QueryBuilders.wildcardQuery("pinYin.keyword", swapKey(dto.getKeyword().toLowerCase(Locale.ROOT))).boost(7.0f));
            boolQuery.must(query);
        }
        builder.query(boolQuery);
    }
相关推荐
皮皮林5516 小时前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
Elasticsearch18 小时前
需要知道某个同义词是否实际匹配了你的 Elasticsearch 查询吗?
elasticsearch
用户908324602733 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
洛森唛4 天前
ElasticSearch查询语句Query String详解:从入门到精通
后端·elasticsearch
用户8307196840824 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解4 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解4 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记4 天前
Spring Boot Web MVC配置详解
spring boot·后端
洛森唛4 天前
Elasticsearch DSL 查询语法大全:从入门到精通
后端·elasticsearch
初次攀爬者5 天前
Kafka 基础介绍
spring boot·kafka·消息队列