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);
    }
相关推荐
小小娥子11 分钟前
【Redis】Hash类型的常用命令
数据库·spring boot·redis
2401_857439691 小时前
“衣依”服装销售平台:Spring Boot技术应用与优化
spring boot·后端·mfc
Elastic 中国社区官方博客2 小时前
Elasticsearch 开放推理 API 增加了对 Google AI Studio 的支持
大数据·数据库·人工智能·elasticsearch·搜索引擎
冷琴19963 小时前
基于java+springboot的酒店预定网站、酒店客房管理系统
java·开发语言·spring boot
九圣残炎3 小时前
【springboot】简易模块化开发项目整合Redis
spring boot·redis·后端
alfiy4 小时前
Elasticsearch学习笔记(六)使用集群令牌将新加点加入集群
笔记·学习·elasticsearch
.生产的驴4 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
帅气的人1234 小时前
使用 docker-compose 启动 es 集群 + kibana
elasticsearch·docker
琴智冰4 小时前
SpringBoot
java·数据库·spring boot
爱码少年4 小时前
springboot工程中使用tcp协议
spring boot·后端·tcp/ip