Dra-M Dra-M
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

莫小龙

保持理智,相信未来。
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Golang

  • 编程思想

  • 微服务

  • 中间件

    • Elasticsearch

      • Spring Data ElasticSearch 快速起步
      • Redis

    • Python

    • 运维

    • 技术
    • 中间件
    • Elasticsearch
    莫小龙
    2020-03-25
    目录

    Spring Data ElasticSearch 快速起步

    pom:

    <dependency>    
        <groupId>org.springframework.boot</groupId>    
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    
    1
    2
    3
    4

    pojo类:

    @Document(indexName = "pojo", type = "docs")
    public class POJO implements Serializable {
        
        @Id
        @Field(index = true, store = true, type = FieldType.Keyword)
        private Long id;
        //是否索引,是否存储,类型,分词器
        @Field(index = true, store = true, type = FieldType.Text, analyzer = "ik_smart")
        private String name;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    mapper类:

    public interface SearchMapper extends ElasticsearchRepository<POJO, Long> {}
    
    1

    配置文件:

    spring:	
    	data:  elasticsearch:    
    		cluster-name: elasticsearch    
    			cluster-nodes: 192.168.200.128:9300
    
    1
    2
    3
    4

    注入对象:

    //简单的CURD
    SearchMapper
    //更底层
    ElasticsearchTemplate
    
    1
    2
    3
    4
    # 查询示例
    @Service
    public class EsSearchServiceImpl implements EsSearchService {
    
    
        @Autowired
        private ElasticsearchTemplate elasticsearchTemplate;
    
    
        @Override
        public Map search(Map<String, String> searchMap) {
    
            Map searchResult = new HashMap();//搜索结果的对象
            if(searchMap==null || searchMap.size()==0){
                return searchResult;
            }
    
            //构建组合查询搜索条件对象BooleanQueryBuilder
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            //判断搜索条件是否为空
            if(StringUtils.isNotEmpty(searchMap.get("keywords"))){
                //模糊搜索
                boolQueryBuilder.must(QueryBuilders.matchQuery("name",searchMap.get("keywords") ).operator(Operator.AND)); // must-and , should - or, mustnot - not
            }
    
            //精确搜索
            if(StringUtils.isNotEmpty(searchMap.get("brand"))){
                boolQueryBuilder.filter(QueryBuilders.termQuery("brandName", searchMap.get("brand")));
            }
    
            //范围搜索
            if(StringUtils.isNotEmpty(searchMap.get("price"))){
                String price = searchMap.get("price"); //价格区间的值格式如: 1000-3000
                String[] split = price.split("-");
                if(split.length==2){
                    String lowPrice = split[0];//获取价格区间最小价格
                    String highPrice = split[1];//获取价格区间最大价格
                    boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(lowPrice).lte(highPrice));
                }
            }
    
            //构建顶级搜索条件对象
            NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
            //添加布尔查询对象
            nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
    
    
            //根据品牌名称进行聚合
            String brandGroup = "brandGroup";
            TermsAggregationBuilder brandGroupBuilder = AggregationBuilders.terms(brandGroup).field("brandName");
            nativeSearchQueryBuilder.addAggregation(brandGroupBuilder);
    
    
    
            //根据价格等进行排序
            if(StringUtils.isNotEmpty(searchMap.get("sortField")) && StringUtils.isNotEmpty(searchMap.get("sortRule"))){
                String sortField = searchMap.get("sortField");
                String sortRule = searchMap.get("sortRule");
                if("DESC".equalsIgnoreCase(sortRule)){
                    nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.DESC));
                } else {
                    nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(SortOrder.ASC));
                }
            }
    
            //分页设置
            int pageNum = 1;
            int pageSize = 20;
            if(StringUtils.isNotEmpty(searchMap.get("pageNum"))){
                pageNum = Integer.valueOf(searchMap.get("pageNum"));
            }
    
            if(StringUtils.isNotEmpty(searchMap.get("pageSize"))){
                pageSize = Integer.valueOf(searchMap.get("pageSize"));
            }
            //ES中分页查询pageNo第一页是0,所以要减1
            nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum-1, pageSize));
    
    
            //高亮设置
            //设置高亮HTML标签
            HighlightBuilder.Field highLightField = new HighlightBuilder.Field("name").preTags("<span style='color:red'>").postTags("</span>");
            nativeSearchQueryBuilder.withHighlightFields(highLightField);
    
    
            //执行搜索
            AggregatedPage<SkuInfo> search = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                    long totalHits = searchResponse.getHits().getTotalHits(); //搜索命中的条数
                    SearchHit[] hits = searchResponse.getHits().getHits();//搜索命中的记录
                    List<T> skuList = new ArrayList<>();
                    if(totalHits>0){
                        for (SearchHit hit : hits) {
                            String skuInfoJson = hit.getSourceAsString(); //搜索命中的每一条记录的JSON字符串
                            SkuInfo skuInfo = JSON.parseObject(skuInfoJson, SkuInfo.class);
                            //需求11.2:取出高亮名称,设置到sku对象中
                            HighlightField field = hit.getHighlightFields().get("name");
    
                            //有高亮字段的时候才处理高亮的名称
                            if(field!=null){
                                Text[] fragments = field.getFragments();
                                if(fragments!=null){
                                    String highlightName = fragments[0].toString();
                                    skuInfo.setName(highlightName);
                                }
                            }
    
                            skuList.add((T)skuInfo);
                        }
                    }
                    //第一个参数:搜索结果集合,第二个参数:分页结果对象 , 第三发参数:搜索命中的条数,第四个参数:聚合结果对象
                    return new AggregatedPageImpl<>(skuList, pageable, totalHits, searchResponse.getAggregations());
                }
            });
    
            //根据聚合分组名查找对应聚合结果集(品牌名称的去重结果集)
            StringTerms brandTerms = (StringTerms)search.getAggregation(brandGroup);
            List<StringTerms.Bucket> brandBuckets = brandTerms.getBuckets();
            List<String> brandList = new ArrayList<>();//这里如果返回给前端,数据格式,将是['小米','华为','苹果']
            if(brandBuckets!=null && brandBuckets.size()>0){
                for (StringTerms.Bucket brandBucket : brandBuckets) {
                    String brandValue = brandBucket.getKeyAsString();
                    brandList.add(brandValue);
                }
            }
            
           
            searchResult.put("rows", search.getContent());//搜索结果记录,如果没有做分页配置那么此处默认是10条数据
            searchResult.put("total",search.getTotalElements());//搜索结果总条数
            searchResult.put("totalPage", search.getTotalPages()); //搜索结果总页数,如果没有做分页配置那么此处默认是1页
            searchResult.put("brandList", brandList);//品牌聚合结果集合,转换为JSON后格式如 ['小米','华为','苹果']
            searchResult.put("pageNum", pageNum);//分页码
            searchResult.put("pageSize", pageSize);//每页显示条数
            return searchResult;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136

    #Elasticsearch
    上次更新: 10/23/2024
    Oauth2+Gateway+JWT+RSA 解决微服务单点登录问题
    Redisson原理

    ← Oauth2+Gateway+JWT+RSA 解决微服务单点登录问题 Redisson原理→

    最近更新
    01
    mosquito配置ws协议
    10-23
    02
    Pip包的离线下载和安装
    10-23
    03
    stable diffusion 相关收藏
    02-24
    更多文章>
    Theme by Vdoing | Copyright © 2019-2024 Dra-M
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式