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);
    }
相关推荐
程序猿小蒜7 分钟前
基于springboot的校园社团信息管理系统开发与设计
java·前端·spring boot·后端·spring
爱淋雨的鼬先生12 分钟前
SpringBoot 概述
java·spring boot·后端
凯子坚持 c16 分钟前
从零开始:开发一个仓颉三方库的完整实战
大数据·elasticsearch·搜索引擎
shepherd12617 分钟前
破局延时任务(下):Spring Boot + DelayQueue 优雅实现分布式延时队列(实战篇)
java·spring boot·分布式
程序员零一25 分钟前
Spring Boot 多 RabbitMQ 连接集成指南
spring boot·rabbitmq
安冬的码畜日常44 分钟前
【JUnit实战3_28】第十七章:用 JUnit 5 实测 SpringBoot 项目
spring boot·功能测试·测试工具·设计模式·单元测试·junit5
李慕婉学姐1 小时前
Springboot的民宿管理系统的设计与实现29rhm9uh(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
李慕婉学姐1 小时前
【开题答辩过程】以《基于微信小程序垃圾分类图像识别技术实现》为例,不会开题答辩的可以进来看看
spring boot·微信小程序·vue
Kay_Liang1 小时前
Spring中@Controller与@RestController核心解析
java·开发语言·spring boot·后端·spring·mvc·注解
陈果然DeepVersion2 小时前
Java大厂面试真题:Spring Boot+Kafka+AI智能客服场景全流程解析(七)
java·人工智能·spring boot·微服务·kafka·面试题·rag