zoukankan      html  css  js  c++  java
  • springboot2.x+整合electricsearch7.0.1

    pom

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     4     <modelVersion>4.0.0</modelVersion>
     5     <parent>
     6         <groupId>org.springframework.boot</groupId>
     7         <artifactId>spring-boot-starter-parent</artifactId>
     8         <version>2.2.5.RELEASE</version>
     9         <relativePath/> <!-- lookup parent from repository -->
    10     </parent>
    11     <groupId>com.example</groupId>
    12     <artifactId>demo</artifactId>
    13     <version>0.0.1-SNAPSHOT</version>
    14     <name>demo</name>
    15     <description>Demo project for Spring Boot</description>
    16 
    17     <properties>
    18         <java.version>1.8</java.version>
    19     </properties>
    20     <repositories>
    21         <repository>
    22             <id>spring-milestones</id>
    23             <name>Spring Milestones</name>
    24             <url>https://repo.spring.io/milestone</url>
    25         </repository>
    26     </repositories>
    27     <dependencies>
    28         <dependency>
    29             <groupId>com.alibaba</groupId>
    30             <artifactId>fastjson</artifactId>
    31             <version>1.2.8</version>
    32         </dependency>
    33         <dependency>
    34             <groupId>org.projectlombok</groupId>
    35             <artifactId>lombok</artifactId>
    36             <optional>true</optional>
    37         </dependency>
    38         <dependency>
    39             <groupId>org.springframework.boot</groupId>
    40             <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    41         </dependency>
    42         <dependency>
    43             <groupId>org.springframework.boot</groupId>
    44             <artifactId>spring-boot-starter-web</artifactId>
    45         </dependency>
    46 
    47         <dependency>
    48             <groupId>org.springframework.boot</groupId>
    49             <artifactId>spring-boot-starter-test</artifactId>
    50             <scope>test</scope>
    51             <exclusions>
    52                 <exclusion>
    53                     <groupId>org.junit.vintage</groupId>
    54                     <artifactId>junit-vintage-engine</artifactId>
    55                 </exclusion>
    56             </exclusions>
    57         </dependency>
    58     </dependencies>
    59     <build>
    60         <plugins>
    61             <plugin>
    62                 <groupId>org.springframework.boot</groupId>
    63                 <artifactId>spring-boot-maven-plugin</artifactId>
    64             </plugin>
    65         </plugins>
    66     </build>
    67 
    68 </project>
    pom
    Goods.java
     1 package com.example.demo;
     2 
     3 import lombok.AllArgsConstructor;
     4 import lombok.NoArgsConstructor;
     5 import org.springframework.data.annotation.Id;
     6 import org.springframework.data.elasticsearch.annotations.Document;
     7 import org.springframework.data.elasticsearch.annotations.Field;
     8 import org.springframework.data.elasticsearch.annotations.FieldType;
     9 
    10 /**
    11  * @Author: pengbenlei
    12  * @Date: 2020/3/9 11:39
    13  * @Description:
    14  */
    15 @NoArgsConstructor
    16 @AllArgsConstructor
    17 @Document(indexName = "item",type = "docs", shards = 1, replicas = 0)
    18 public class Goods {
    19     @Id
    20     private Long id;
    21     @Field(type = FieldType.Text, analyzer = "ik_max_word")
    22     private String title; //标题
    23     @Field(type = FieldType.Keyword)
    24     private String category;// 分类
    25     @Field(type = FieldType.Keyword)
    26     private String brand; // 品牌
    27     @Field(type = FieldType.Double)
    28     private Double price; // 价格
    29     @Field(index = false, type = FieldType.Keyword)
    30     private String images; // 图片地址
    31 
    32     public Goods(long id, String title, String category, String brand, double price, String images) {
    33         this.id=id;
    34         this.title=title;
    35         this.category=category;
    36         this.brand=brand;
    37         this.price=price;
    38         this.images=images;
    39     }
    40 
    41     public Long getId() {
    42         return id;
    43     }
    44 
    45     public void setId(Long id) {
    46         this.id = id;
    47     }
    48 
    49     public String getTitle() {
    50         return title;
    51     }
    52 
    53     public void setTitle(String title) {
    54         this.title = title;
    55     }
    56 
    57     public String getCategory() {
    58         return category;
    59     }
    60 
    61     public void setCategory(String category) {
    62         this.category = category;
    63     }
    64 
    65     public String getBrand() {
    66         return brand;
    67     }
    68 
    69     public void setBrand(String brand) {
    70         this.brand = brand;
    71     }
    72 
    73     public Double getPrice() {
    74         return price;
    75     }
    76 
    77     public void setPrice(Double price) {
    78         this.price = price;
    79     }
    80 
    81     public String getImages() {
    82         return images;
    83     }
    84 
    85     public void setImages(String images) {
    86         this.images = images;
    87     }
    88 }
    商品类
    商品类中有几个注解,解释一下:
    1、@Document (相当于Hibernate实体的@Entity/@Table)(必写),加上了@Document注解之后,默认情况下这个实体中所有的属性都会被建立索引、并且分词。
    Document参数对照表
    类型 属性名 默认值 说明
    String indexName
    无 索引库的名称,建议以项目的名称命名
     
    String type ""
    类型,建议以实体的名称命名
    short shards 5
    默认分区数
    short replica 1
    每个分区默认的备份数
    String refreshInterval "1s" 刷新间隔
    String indexStoreType "fs" 索引文件储存

    2、@Id (相当于Hibernate实体的主键@Id注解)(必写)
    3、@Field (相当于Hibernate实体的@Column注解),@Field默认是可以不加的,默认所有属性都会添加到ES中。加上@Field之后,@document默认把所有字段加上索引失效,只有加@Field 才会被索引(同时也看设置索引的属性是否为no)

                                Field 参数对照表

    类型 属性名 默认值 说明
    FieldType type FieldType.Auto 自动检测属性的类型
    FieldIndex index FieldIndex.analyzed 默认情况下粉尘
    boolean store false 默认情况下不存储原文
    String searchAnalyzer "" 指定字段搜索是使用的分词器
    String indexAnalyzer "" 指定字段建立索引时指定的分词器
    String[] ignoreFields {} 如果某个字段需要被忽略
    
    
    type:字段类型,是是枚举:FieldType,可以是text、long、short、date、integer、object等
    text:存储数据时候,会自动分词,并生成索引
    keyword:存储数据时候,不会分词建立索引
    Numerical:数值类型,分两类
    基本数据类型:long、interger、short、byte、double、float、half_float
    浮点数的高精度类型:scaled_float
    需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
    Date:日期类型
    elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
    index:是否索引,布尔类型,默认是true
    store:是否存储,布尔类型,默认是false
    analyzer:分词器名称,这里的ik_max_word即使用ik分词器
    GoodsRepository.java
     1 package com.example.demo;
     2 
     3 import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
     4 import org.springframework.stereotype.Component;
     5 
     6 import java.util.List;
     7 
     8 /**
     9  * @Author: pengbenlei
    10  * @Date: 2020/3/9 11:40
    11  * @Description:
    12  */
    13 @Component
    14 public interface GoodsRepository extends ElasticsearchRepository<Goods,Long> {
    15 
    16     /**
    17      * 根据价格区间查询
    18      * @param price1
    19      * @param price2
    20      * @return
    21      */
    22     List<Goods> findByPriceBetween(double price1, double price2);
    23 
    24     Goods findByTitle(String title);
    25 }
    商品仓接口

    其中有两个方法,没有实现,确能正常执行,是因为方法名称中的Between和findBy关键字,es会智能根据关键字和字段名称拼接查询,对照表如下:

    查询关键字对照表
    关键字 方法名称实例  
    And findByNameAndPrice }
    Or findByNameOrPrice  
    Is findByName  
    Not findByNameNot  
    Between findByPriceBetween  
    LessThanEqual findByPriceLessThan  
    GreaterThanEqual findByPriceGreaterThan  
    Before findByPriceBefore  
    After findByPriceAfter  
    Like findByNameLike  
    StartingWith findByNameStartingWith  
    EndingWith findByNameEndingWith  
    Contains/Containing findByNameContaining  
    In
    findByNameIn(Collection<String>names)
     
    NotIn
    findByNameNotIn(Collection<String>names)
     
    Near
    findByStoreNear Not Supported Yet !
     
    True findByAvailableTrue  
    False findByAvailableFalse  
    OrderBy findByAvailableTrueOrderByNameDesc  

     

    基础测试类:

      1 package com.example.demo;
      2 
      3 import com.alibaba.fastjson.JSON;
      4 import org.elasticsearch.action.get.MultiGetRequest;
      5 import org.elasticsearch.client.Client;
      6 import org.elasticsearch.client.RestHighLevelClient;
      7 import org.elasticsearch.index.query.MatchQueryBuilder;
      8 import org.elasticsearch.index.query.QueryBuilders;
      9 import org.elasticsearch.search.aggregations.AggregationBuilders;
     10 import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
     11 import org.elasticsearch.search.aggregations.metrics.avg.InternalAvg;
     12 import org.elasticsearch.search.sort.SortBuilders;
     13 import org.elasticsearch.search.sort.SortOrder;
     14 import org.junit.jupiter.api.Test;
     15 import org.springframework.beans.factory.annotation.Autowired;
     16 import org.springframework.boot.test.context.SpringBootTest;
     17 import org.springframework.data.domain.Page;
     18 import org.springframework.data.domain.PageRequest;
     19 import org.springframework.data.domain.Sort;
     20 import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
     21 import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
     22 import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
     23 import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
     24 
     25 import java.util.ArrayList;
     26 import java.util.List;
     27 
     28 @SpringBootTest
     29 class DemoApplicationTests {
     30     @Autowired
     31     GoodsRepository goodsRepository;
     32     @Test
     33     void contextLoads() {
     34     }
     35 //    @Autowired
     36 //    private ElasticsearchTemplate elasticsearchTemplate;
     37 
     38 
     39 
     40 
     41     @Test
     42     public void addDocument() {
     43         Goods goods = new Goods(1L, "大米1S", "手机",
     44                 "大米", 3499.00, "https://img13.360buyimg.com/n1/s450x450_jfs/t1/79993/29/9874/153231/5d7809f4E8f387bff/1dc9e1b6b262f0fb.jpg");
     45         Goods goods0 = goodsRepository.save(goods);
     46         System.out.println(JSON.toJSONString(goods0));
     47     }
     48 
     49     /**
     50      * 批量新增
     51      */
     52     @Test
     53     public void createDocumentList() {
     54         List<Goods> list = new ArrayList<>();
     55         list.add(new Goods(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.leyou.com/123.jpg"));
     56         list.add(new Goods(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.leyou.com/3.jpg"));
     57         // 接收对象集合,实现批量新增
     58         goodsRepository.saveAll(list);
     59     }
     60 
     61     @Test
     62     public void findDocument() {
     63         // 查询全部,并安装价格降序排序
     64         Iterable<Goods> goodsIterable = this.goodsRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
     65         goodsIterable.forEach(goods -> System.out.println(JSON.toJSONString(goods)));
     66     }
     67 
     68     @Test
     69     public void indexList() {
     70         List<Goods> list = new ArrayList<>();
     71         list.add(new Goods(1L, "小米手机7", "手机", "小米", 3299.00, "http://image.leyou.com/13123.jpg"));
     72         list.add(new Goods(2L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.leyou.com/13123.jpg"));
     73         list.add(new Goods(3L, "华为META10", "手机", "华为", 4499.00, "http://image.leyou.com/13123.jpg"));
     74         list.add(new Goods(4L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.leyou.com/13123.jpg"));
     75         list.add(new Goods(5L, "荣耀V10", "手机", "华为", 2799.00, "http://image.leyou.com/13123.jpg"));
     76         // 接收对象集合,实现批量新增
     77         goodsRepository.saveAll(list);
     78     }
     79 
     80     @Test
     81     public void queryByPriceBetween(){
     82         List<Goods> list = this.goodsRepository.findByPriceBetween(2000.00, 3500.00);
     83         for (Goods goods: list) {
     84             System.out.println(goods);
     85         }
     86     }
     87     @Test
     88     public void testQuery(){
     89         MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("id", "1");
     90         Iterable<Goods> items =goodsRepository.search(queryBuilder);
     91         for (Goods item : items) {
     92             System.out.println(JSON.toJSONString(item));
     93         }
     94     }
     95 
     96     @Test
     97     void findByTitle()
     98     {
     99         Goods goods= goodsRepository.findByTitle("小米Mix2S");
    100         System.out.println(JSON.toJSONString(goods));
    101     }
    102 
    103 
    104     @Test
    105     public void testNativeQuery(){
    106         // 构建查询条件
    107         NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    108         // 添加基本的分词查询
    109         queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
    110 
    111         // 初始化分页参数
    112         int page = 0;
    113         int size = 20;
    114         // 设置分页参数
    115         queryBuilder.withPageable(PageRequest.of(page, size));
    116 
    117         // 执行搜索,获取结果
    118         Page<Goods> items = goodsRepository.search(queryBuilder.build());
    119         // 打印总条数
    120         System.out.println(items.getTotalElements());
    121         // 打印总页数
    122         System.out.println(items.getTotalPages());
    123         // 每页大小
    124         System.out.println(items.getSize());
    125         // 当前页
    126         System.out.println(items.getNumber());
    127         for (Goods item : items) {
    128             System.out.println(JSON.toJSONString(item));
    129         }
    130     }
    131     @Test
    132     public void testSort(){
    133         // 构建查询条件
    134         NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    135         // 添加基本的分词查询
    136         queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
    137 
    138         // 排序
    139         queryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC));
    140 
    141         // 执行搜索,获取结果
    142         Page<Goods> items = goodsRepository.search(queryBuilder.build());
    143         // 打印总条数
    144         System.out.println(items.getTotalElements());
    145         for (Goods item : items) {
    146             System.out.println(JSON.toJSONString(item));
    147         }
    148     }
    149     @Test
    150     /**
    151      * 按照品牌brand进行分组 统计各品牌的总数
    152      * */
    153     public void testAgg(){
    154         NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    155         // 不查询任何结果
    156         queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    157         // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    158         queryBuilder.addAggregation(
    159                 AggregationBuilders.terms("brands").field("brand"));
    160         // 2、查询,需要把结果强转为AggregatedPage类型
    161         AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) goodsRepository.search(queryBuilder.build());
    162         // 3、解析
    163         // 3.1、从结果中取出名为brands的那个聚合,
    164         // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    165         StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
    166         // 3.2、获取桶
    167         List<StringTerms.Bucket> buckets = agg.getBuckets();
    168         // 3.3、遍历
    169         for (StringTerms.Bucket bucket : buckets) {
    170             // 3.4、获取桶中的key,即品牌名称
    171             System.out.println(bucket.getKeyAsString());
    172             // 3.5、获取桶中的文档数量
    173             System.out.println(bucket.getDocCount());
    174         }
    175     }
    176     @Test
    177     /**
    178      * 嵌套聚合,求平均值
    179      * */
    180     public void testSubAgg(){
    181         NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    182         // 不查询任何结果
    183         queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    184         // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    185         queryBuilder.addAggregation(
    186                 AggregationBuilders.terms("brands").field("brand")
    187                         .subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值
    188         );
    189         // 2、查询,需要把结果强转为AggregatedPage类型
    190         AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) goodsRepository.search(queryBuilder.build());
    191         // 3、解析
    192         // 3.1、从结果中取出名为brands的那个聚合,
    193         // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    194         StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
    195         // 3.2、获取桶
    196         List<StringTerms.Bucket> buckets = agg.getBuckets();
    197         // 3.3、遍历
    198         for (StringTerms.Bucket bucket : buckets) {
    199             // 3.4、获取桶中的key,即品牌名称  3.5、获取桶中的文档数量
    200             System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");
    201 
    202             // 3.6.获取子聚合结果:
    203             InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
    204             System.out.println("平均售价:" + avg.getValue());
    205         }
    206     }
    207 
    208 }
    功能测试类

     demo源码:https://github.com/Rolayer/springboot2.x-electricsearch7.0.1

  • 相关阅读:
    对mysql 数据库操作 使其支持插入中文(针对python)
    网页制作中的超链接怎么做
    python requests的安装与简单运用(转)
    ubuntu 修改权限
    [Linux]常用命令与目录全拼
    Python web 简单服务器的搭建与运行
    ubuntu 下终端关于调试C++的命令
    正则表达式基本语法详解
    Linux下 编译C++/C以及常用的几种命令(ubuntu)
    Visual Studio 2013 中 mysql 使用 EF6
  • 原文地址:https://www.cnblogs.com/rolayblog/p/12450009.html
Copyright © 2011-2022 走看看