SpringBoot整合Spring Data Elasticsearch

特点:

  • 分布式,无需人工搭建集群(solr就需要人为配置,使用Zookeeper作为注册中心)
  • Restful风格,一切API都遵循Rest原则,容易上手
  • 近实时搜索,数据更新在Elasticsearch中几乎是完全同步的

倒排索引
倒排索引是引擎搜素的基础;
在存文档的时候,将数据进行分词,并记录每个分词下的文档编号,查找的通过分词找到对应的倒排列表的数据
安装es
点击:官网下载es
在这里插入图片描述

  • 将下载的压缩包解压到自定义目录即可
    在这里插入图片描述
    执行该文件,浏览器访问http://localhost:9200/
    Java程序访问端口9300
    在这里插入图片描述
    安装Head插件
    elasticsearch-head相当于可视化工具
    此链接下载Head插件,解压即可
    确保已安装
    node及grunt
    在这里插入图片描述

  • grunt下载:npm install -g grunt-cli

  • 通过npm run start 开启
    在这里插入图片描述

访问localhost:9100
在这里插入图片描述
安装IK分词器
Elastic Search默认的分词器是单个分词,效果很差
下载 一定要选择与Elastic Search版本同步

  • 将下载的Ik分词器改名为ik放在elasticsearch的目录下
    在这里插入图片描述

  • 重启es,如下图成功
    在这里插入图片描述

  • 在IKAnalyzer.cfg.xml中配置扩展词和停用词(根据需要)
    在这里插入图片描述

SpringBoot整合Spring Data Elasticsearch

SpringDataElasticSearch是SpringData项目下的一个子模块
SpringData的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。

  • 所需依赖
        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-elasticsearch -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>4.0.0.RELEASE</version>
        </dependency>
  • application.yml配置文件
spring:
  data:
    elasticsearch:
      cluster-name: my-application
      cluster-nodes: 127.0.0.1:9300 # 程序连接es的端口号是9300

在这里插入图片描述
在SpringDataElasticSearch中,只需要操作对象,就可以操作elasticsearch中的数据

索引操作
  • 创建索引及映射

    • @Document 作用在类,标记实体类为文档对象,一般有两个属性

      • indexName:对应索引库名称
      • type:对应在索引库中的类型
      • shards:分片数量,默认5
      • replicas:副本数量,默认1
    • @Id 作用在成员变量,标记一个字段作为id主键

    • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:

  • 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分词器

POJO

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "student")
@Document(indexName = "capgeminitest",type = "student")
public class Student {
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "JDBC")
    private Integer id;

    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    @Column(name = "sname")
    private String sname;
}

测试

@RestController
@RequestMapping("/stu")
public class StudentController {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @GetMapping
    public void testEs(){
        // 创建索引
        elasticsearchTemplate.createIndex(Student.class);
        // 映射
        elasticsearchTemplate.putMapping(Student.class);
        Logger.getLogger("Esearch").info("创建索引测试成功");
    }

    @DeleteMapping
    public void testDelEs(){
        // 删除索引
        elasticsearchTemplate.deleteIndex(Student.class);
        Logger.getLogger("Esearch").info("删除索引测试成功");
    }
}

在这里插入图片描述

  • 新增文档数据
    Repository接口
    不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。只要你定义一个接口,然后继承Repository提供的一些子接口
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {
}

  • 添加一个对象,批量添加
@RestController
@RequestMapping("/stu")
public class StudentController {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private StudentRepository studentRepository;
    @GetMapping("/addAllStu")
    public void addAllStu(){
        Student student = new Student();
        student.setSname("李木子");
        Student student2 = new Student();
        student2.setSname("李七夜");
        ArrayList<Student> students = new ArrayList<>();
        students.add(student);
        students.add(student2);
        studentRepository.saveAll(students);
        Logger.getLogger("Esearch").info("批量新增对象测试成功");
    }
    @GetMapping("/addStu")
    public void addStu(){
        Student student = new Student();
        student.setSname("李淳罡");
        studentRepository.save(student);
        Logger.getLogger("Esearch").info("添加一个对象测试成功");
    }
}

页面查询
在这里插入图片描述
没有修改,需先删除,再修改,根据id作为依据

查询

查询

  • 基本查询
    在这里插入图片描述
  • 分页查询
    在这里插入图片描述
  • 排序查找
    ascending升序
    descending降序在这里插入图片描述
  • 自定义方法(SpringData的功能,根据方法名自动实现功能)
KeywordSample
AndfindByTitleAndPricefindBy属性名1And属性名2
OrfindByTitleOrPrice
Is=findByTitle
NotfindByTitleNot
BetweenfindByPriceBetween
LessThanEqualfindByPriceLessThan
GreaterThanEqualfindByPriceGreaterThan
BeforefindByPriceBefore
AfterfindByPriceAfter
LikefindByNameLike
StartingWithfindByNameStartingWith
EndingWithfindByNameEndingWith
Contains/ContainingfindByNameContaining
InfindByNameIn(Collectionnames)
NotInfindByNameNotIn(Collectionnames)
NearfindByStoreNear
TruefindByAvailableTrue
FalsefindByAvailableFalse
OrderByfindByAvailableTrueOrderByNameDesc

自定义方法

- id在x-y之间
- id在x-y之间并倒序
- 模糊匹配
  • Repository
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {
    /**
     * 根据id区间搜索
     */
    public List<Student> findByidBetween(Integer id, Integer id2);

    /**
     * 模糊匹配
     * @param sname
     * @return
     */
    public List<Student> findBySname(String sname);
    /**
     * id在xxx-yyy区间内的,并且根据id倒序排序输出
     *
     */
    public List<Student> findByidBetweenOrderByIdDesc(Integer id, Integer id2);

}
  • 测试
@RestController
@RequestMapping("/stu")
public class StudentController {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private StudentRepository studentRepository;

    /**
     * 基本查询
     */
    @GetMapping("/queryAll")
    public void query(){
        Iterable<Student> all = studentRepository.findAll();
        Iterator<Student> iterator = all.iterator();
        while (iterator.hasNext()){
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info(""+iterator.next());
        }
    }

    /**
     * 分页查询
     * @param page    页数
     * @param size    数量
     */
    @GetMapping("/limitPage")
    public void findPage(int page, int size){
        Page<Student> all = studentRepository.findAll(PageRequest.of(page, size));
        for (Student student : all) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("分页:"+student);
        }
        EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("总条数"+all.getTotalElements());
        EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("总页数"+all.getTotalPages());
    }

    /**
     * 排序查询
     */
    @GetMapping("/findAllOrder")
    public void findAllOrder(){
        // 降序
        Iterable<Student> id = studentRepository.findAll(Sort.by("id").descending());
        for (Student student : id) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("根据id进行排序查找:"+student);
        }
    }

    /**
     * 查找id在x-y之间的数据
     * @param id
     * @param id2
     */
    @GetMapping("/findIdBetween")
    public void findIdBetween(Integer id, Integer id2){
        List<Student> byIdBetween = studentRepository.findByidBetween(id, id2);
        for (Student student : byIdBetween) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("id在x-y之间"+student);
        }
    }

    /**
     * 查找id在x-y之间的数据并倒序打印
     * @param id
     * @param id2
     */
    @GetMapping("/findByIDBetweenOrderByIdDesc")
    public void findByIDBetweenOrderByIdDesc(Integer id, Integer id2){
        List<Student> byIDBetweenOrderByIdDesc = studentRepository.findByidBetweenOrderByIdDesc(id, id2);
        for (Student student : byIDBetweenOrderByIdDesc) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("id在x-y之间,并按id倒序查询"+student);
        }
    }

    /**
     * 模糊匹配
     * @param sname
     */
    @GetMapping("/findBySname")
    public void findBySname(String sname){
        List<Student> bySname = studentRepository.findBySname(sname);
        for (Student student : bySname) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("模糊匹配"+student);
        }
    }

}

自定义查询
NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体

  • matchQuery:词条匹配,先分词然后在调用termQuery进行匹配
  • TermQuery:词条匹配,不分词
  • wildcardQuery:通配符匹配
  • fuzzyQuery:模糊匹配(允许错两个字母)
  • rangeQuery:范围匹配
  • booleanQuery:布尔查询
    分页—排序----高亮
@RestController
@RequestMapping("/stu2")
public class StudnetController2 {
    @Resource
    private StudentRepository studentRepository;

    /**
     * 自定义查询  分词 matchQuery
     *
     * @param sname
     */
    @GetMapping("/testSearch")
    public void testSearch(String sname) {
        // 创建查询构建器- 构建条件
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // 构建条件
        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("sname", sname));
        Page<Student> search = studentRepository.search(nativeSearchQueryBuilder.build());
        for (Student student : search) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("先分词,在调用termQuery进行匹配" + student);
        }
    }

    /**
     * 不分词匹配   termQuery
     *
     * @param sname
     */
    @GetMapping("/testQuery")
    public void testQuery(String sname) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("sname", sname));
        Page<Student> search = studentRepository.search(nativeSearchQueryBuilder.build());
        for (Student student : search) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("词条匹配,不分词" + student);
        }
    }

    /**
     * 分页查询
     *
     * @param page  第n页
     * @param size  每页y条数据
     * @param sname
     */
    @GetMapping("/testPage")
    public void testPage(int page, int size, String sname) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("sname", sname));
        // 进行分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(page, size));
        Page<Student> search = studentRepository.search(nativeSearchQueryBuilder.build());
        for (Student student : search) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("分页查询:" + student);
        }
    }

    /**
     * 排序查询
     *
     * @param sname
     */
    @GetMapping("/testOrder")
    public void testOrder(String sname) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("sname", sname));
        // 进行排序
        nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC));
        Page<Student> search = studentRepository.search(nativeSearchQueryBuilder.build());
        for (Student student : search) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("按照id降序排序查找Sname:" + student);
        }
    }

    /**
     * 高亮显示
     * @param sname
     */
    @GetMapping("/testHighlight")
    public void testHighlight(String sname) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.fuzzyQuery("sname", sname));
        nativeSearchQueryBuilder.
                withHighlightFields(new HighlightBuilder.
                        Field("sname").
                        // 添加前缀和后缀
                        preTags("<em>").postTags("<em>"));
        Page<Student> search = studentRepository.search(nativeSearchQueryBuilder.build());
        for (Student student : search) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("高亮显示:"+student);
        }
    }

}

聚合 桶bucket
(1)统计某个字段的数量
ValueCountBuilder vcb = AggregationBuilders.count(“count_uid”).field(“uid”);
(2)去重统计某个字段的数量(有少量误差)
CardinalityBuilder cb =AggregationBuilders.cardinality(“distinct_count_uid”).field(“uid”);
(3)按日期间隔分组
DateHistogramBuilder dhb = AggregationBuilders.dateHistogram(“dh”).field(“date”);
(4)按某个字段分组
TermsBuilder tb = AggregationBuilders.terms(“group_name”).field(“name”);
(5)求和
SumBuilder sumBuilder = AggregationBuilders.sum(“sum_price”).field(“price”);
(6)求平均
AvgBuilder ab=
AggregationBuilders.avg(“avg_price”).field(“price”);
(7)求最大值
MaxBuilder mb = AggregationBuilders.max(“max_price”).field(“price”);
(8)求最小值
MinBuilder min = AggregationBuilders.min(“min_price”).field(“price”);
(9)聚合过滤
FilterAggregationBuilder fab = AggregationBuilders.filter(“uid_filter”).filter(QueryBuilders.queryStringQuery(“uid:001”));
(10)获取聚合里面的结果
平均值
TopHitsBuilder thb = AggregationBuilders.topHits(“top_result”);
(11)嵌套的聚合
NestedBuilder nb = AggregationBuilders.nested(“negsted_path”).path(“quests”);
(12)反转嵌套
AggregationBuilders.reverseNested(“res_negsted”).path(“kps”);

在这里插入代码片 /**
     * 聚合    分组
     */
    @GetMapping("/testBucket")
    public void testBucket() {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // 添加分组,分组名称brands,根据id分组
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("id"));
        // 查询.放到聚合分组
        AggregatedPage<Student> search = (AggregatedPage<Student>) studentRepository.search(nativeSearchQueryBuilder.build());
        // 根据键取出数据
        StringTerms stringTerms = (StringTerms) search.getAggregation("brands");
        List<StringTerms.Bucket> buckets = stringTerms.getBuckets();
        for (StringTerms.Bucket bucket : buckets) {
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("分组后名称:"+bucket.getKeyAsString());
            EsearchConsont.ElASTICSEARCH_LOG_CONSONT.info("分组后数量:"+bucket.getDocCount());
        }
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值