栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

Spring Data Elasticsearch--入门/使用/用法/实例/教程/客户端--SpringBoot整合--spring-boot-starter-data-elasticsearch

Spring Data Elasticsearch--入门/使用/用法/实例/教程/客户端--SpringBoot整合--spring-boot-starter-data-elasticsearch

原文网址:Spring Data Elasticsearch--入门/使用/用法/实例/教程/客户端--SpringBoot整合--spring-boot-starter-data-elasticsearch_IT利刃出鞘的博客-CSDN博客

简介

说明

        spring-data-elasticsearch是比较好用的一个elasticsearch客户端,本文介绍如何使用它来操作ES。本文使用spring-boot-starter-data-elasticsearch,它内部会引入spring-data-elasticsearch。

        Spring Data ElasticSearch有下边这几种方法操作ElasticSearch:

  1. ElasticsearchRepository(传统的方法,可以使用)
  2. ElasticsearchRestTemplate(推荐使用。基于RestHighLevelClient)
  3. ElasticsearchTemplate(ES7中废弃,不建议使用。基于TransportClient)
  4. RestHighLevelClient(推荐度低于ElasticsearchRestTemplate,因为API不够高级)
  5. TransportClient(ES7中废弃,不建议使用)

        本文仅展示使用ElasticsearchRepository的操作。

官网

官网文档:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/

本文依赖版本

  • spring-boot-starter-parent:2.3.12.RELEASE
  • spring-boot-starter-data-elasticsearch:2.3.12.RELEASE
    • spring-data-elasticsearch:4.0.9.RELEASE
  • ES服务端:7.15.0

        spring-data-elasticsearch:4.0的比较重大的修改:4.0对应支持ES版本为7.6.2,并且弃用了对TransportClient的使用(默认使用High Level REST Client)。

        ES从7.x版本开始弃用了对TransportClient的使用,并将会在8.0版本开始完全删除TransportClient。

        TransportClient:使用9300端口通过TCP与ES连接,不好用,且有高并发的问题。

        High Level REST Client:使用9200端口通过HTTP与ES连接,很好用,性能高。

版本对应大全

Elasticsearch 对于版本的兼容性要求很高,大版本之间是不兼容的。

spring-data-elasticsearch与ES、SpringBoot的对应关系如下。截取自官网

详细的版本对应如下:

Elasticsearch1(Spring Data Elasticsearch 1)
序号Elasticsearch版本Spring Data Elasticsearch版本spring-boot-starter-data-elasticsearch版本
11.1.11.0.0.RELEASE
21.3.21.1.0.RELEASE
31.4.41.2.0.RELEASE
41.5.21.3.0.RELEASE/1.3.x
51.7.31.4.0.M1
Elasticsearch 2(Spring Data Elasticsearch 2)(Sring Boot 1)
序号Elasticsearch版本Spring Data Elasticsearch版本spring-boot-starter-data-elasticsearch版本
12.2.02.0.0.RELEASE/2.0.x
22.4.02.0.4.RELEASE/2.1.x1.5.x
Elasticsearch 5(Spring Data Elasticsearch 3)(Sring Boot 2)
序号Elasticsearch版本Spring Data Elasticsearch版本spring-boot-starter-data-elasticsearch版本
15.4.03.0.0.M4
25.5.03.0.0.RC2/3.0.x2.0.x
Elasticsearch 6(Spring Data Elasticsearch 3)(Sring Boot 2)
序号Elasticsearch版本Spring Data Elasticsearch版本spring-boot-starter-data-elasticsearch版本
16.2.2

3.1.1.RELEASE/3.1.3.RELEASE

/3.1.x

2.1.1.RELEASE/2.1.x
26.8.123.2.x2.2.x
Elasticsearch 7(Spring Data Elasticsearch 3)(Sring Boot 2)
序号Elasticsearch版本Spring Data Elasticsearch版本spring-boot-starter-data-elasticsearch版本
17.6.2

4.0.x

2.3.x
27.9.34.1.6/4.1.8/4.1.x2.4.4/2.4.5/2.4.x
37.12.04.2.x2.5.x
47.13.34.3.x2.5.x
公共代码 依赖及配置

主要是这个依赖:


    org.springframework.boot
    spring-boot-starter-data-elasticsearch

下边贴出我的整个pom.xml



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.12.RELEASE
         
    
    com.example
    demo_spring-data-elasticsearch
    0.0.1-SNAPSHOT
    demo_spring-data-elasticsearch
    demo_spring-data-elasticsearch
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            com.github.xiaoymin
            knife4j-spring-boot-starter
            3.0.3
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    


配置(application.yml )

spring:
  elasticsearch:
    rest:
      uris: http://127.0.0.1:9200
      # username: xxx
      # password: yyy
      # connection-timeout: 1
      # read-timeout: 30

# 上边是客户端High Level REST Client的配置,推荐使用。

# 下边是reactive客户端的配置,非官方,不推荐。
#  data:
#    elasticsearch:
#      client:
#        reactive:
#          endpoints: 127.0.0.1:9200
#          username: xxx
#          password: yyy
#          connection-timeout: 1
#          socket-timeout: 30
#          use-ssl: false
索引结构

索引结构

http://localhost:9200/
PUT blog

{
    "settings": {
        "number_of_shards": 5,
        "number_of_replicas": 1
    },
    "mappings": {
        "properties": {
            "id":{
                "type":"long"
            },
            "title": {
                "type": "text"
            },
            "content": {
                "type": "text"
            },
            "author":{
                "type": "text"
            },
            "category":{
                "type": "keyword"
            },
            "createTime": {
                "type": "date",
                "format":"yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||epoch_millis"
            },
            "updateTime": {
                "type": "date",
                "format":"yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||epoch_millis"
            },
            "status":{
                "type":"integer"
            },
            "serialNum": {
                "type": "keyword"
            }
        }
    }
}
Entity/Dao

Entity

package com.example.demo.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
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.util.Date;

@Data
@document(indexName = "blog", shards = 1, replicas = 1)
public class Blog {
    //此项作为id,不会写到_source里边。
    @Id
    private Long blogId;

    @Field(type = FieldType.Text)
    private String title;

    @Field(type = FieldType.Text)
    private String content;

    @Field(type = FieldType.Text)
    private String author;

    //博客所属分类。
    @Field(type = FieldType.Keyword)
    private String category;

    //0: 未发布(草稿) 1:已发布 2:已删除
    @Field(type = FieldType.Integer)
    private int status;

    //序列号,用于给外部展示的id
    @Field(type = FieldType.Keyword)
    private String serialNum;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @Field(type= FieldType.Date, format= DateFormat.custom, pattern="yyyy-MM-dd HH:mm:ss.SSS")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @Field(type=FieldType.Date, format=DateFormat.custom, pattern="yyyy-MM-dd HH:mm:ss.SSS")
    private Date updateTime;
}

Dao

package com.example.demo.dao;

import com.example.demo.entity.Blog;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface BlogRepository extends ElasticsearchRepository {

}
增删改查(CrudRepository) 简介

接口的继承

所有方法

实例

代码

package com.example.demo.controller;

import com.example.demo.dao.BlogRepository;
import com.example.demo.entity.Blog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Api(tags = "增删改查(文档)")
@RestController
@RequestMapping("crud")
public class CrudController {
    @Autowired
    private BlogRepository blogRepository;

    @ApiOperation("添加单个文档")
    @PostMapping("adddocument")
    public Blog adddocument() {
        Long id = 1L;
        Blog blog = new Blog();
        blog.setBlogId(id);
        blog.setTitle("Spring Data ElasticSearch学习教程" + id);
        blog.setContent("这是添加单个文档的实例" + id);
        blog.setAuthor("Tony");
        blog.setCategory("ElasticSearch");
        blog.setCreateTime(new Date());
        blog.setStatus(1);
        blog.setSerialNum(id.toString());

        return blogRepository.save(blog);
    }

    @ApiOperation("添加多个文档")
    @PostMapping("adddocuments")
    public Object adddocuments(Integer count) {
        List blogs = new ArrayList<>();
        for (int i = 1; i <= count; i++) {
            Long id = (long)i;
            Blog blog = new Blog();
            blog.setBlogId(id);
            blog.setTitle("Spring Data ElasticSearch学习教程" + id);
            blog.setContent("这是添加单个文档的实例" + id);
            blog.setAuthor("Tony");
            blog.setCategory("ElasticSearch");
            blog.setCreateTime(new Date());
            blog.setStatus(1);
            blog.setSerialNum(id.toString());
            blogs.add(blog);
        }

        return blogRepository.saveAll(blogs);
    }

    
    @ApiOperation("修改单个文档")
    @PostMapping("editdocument")
    public Blog editdocument() {
        Long id = 1L;
        Blog blog = new Blog();
        blog.setBlogId(id);
        blog.setTitle("Spring Data ElasticSearch学习教程" + id);
        blog.setContent("这是修改单个文档的实例" + id);
        // blog.setAuthor("Tony");
        // blog.setCategory("ElasticSearch");
        // blog.setCreateTime(new Date());
        // blog.setStatus(1);
        // blog.setSerialNum(id.toString());

        return blogRepository.save(blog);
    }

    @ApiOperation("查找单个文档")
    @GetMapping("findById")
    public Blog findById(Long id) {
        return blogRepository.findById(id).get();
    }

    @ApiOperation("删除单个文档")
    @PostMapping("deletedocument")
    public String deletedocument(Long id) {
        blogRepository.deleteById(id);
        return "success";
    }

    @ApiOperation("删除所有文档")
    @PostMapping("deletedocumentAll")
    public String deletedocumentAll() {
        blogRepository.deleteAll();
        return "success";
    }
}

测试1:添加单个文档

head结果

测试2:添加多个文档

head结果

测试3:修改单个文档

head结果

测试4:查找单个文档

测试5:删除单个文档

head结果

测试6:删除所有文档

head结果

自定义方法查询 简介

跟Spring Data JPA类似,spring data elsaticsearch提供了自定义方法的查询方式:

在Repository接口中自定义方法,spring data根据方法名,自动生成实现类,方法名必须符合一定的规则,如下表所示(摘录自官网):

Keyword

Sample

Elasticsearch Query String

And

findByNameAndPrice

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}

Or

findByNameOrPrice

{ "query" : { "bool" : { "should" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}

Is

findByName

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}

Not

findByNameNot

{ "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}

Between

findByPriceBetween

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}

LessThan

findByPriceLessThan

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } } ] } }}

LessThanEqual

findByPriceLessThanEqual

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}

GreaterThan

findByPriceGreaterThan

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } } ] } }}

GreaterThanEqual

findByPriceGreaterThan

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}

Before

findByPriceBefore

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}

After

findByPriceAfter

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}

Like

findByNameLike

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

StartingWith

findByNameStartingWith

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

EndingWith

findByNameEndingWith

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

Contains/Containing

findByNameContaining

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

In (when annotated as FieldType.Keyword)

findByNameIn(Collectionnames)

{ "query" : { "bool" : { "must" : [ {"bool" : {"must" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}

In

findByNameIn(Collectionnames)

{ "query": {"bool": {"must": [{"query_string":{"query": ""?" "?"", "fields": ["name"]}}]}}}

NotIn (when annotated as FieldType.Keyword)

findByNameNotIn(Collectionnames)

{ "query" : { "bool" : { "must" : [ {"bool" : {"must_not" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}

NotIn

findByNameNotIn(Collectionnames)

{"query": {"bool": {"must": [{"query_string": {"query": "NOT("?" "?")", "fields": ["name"]}}]}}}

Near

findByStoreNear

Not Supported Yet !

True

findByAvailableTrue

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }}

False

findByAvailableFalse

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "false", "fields" : [ "available" ] } } ] } }}

OrderBy

findByAvailableTrueOrderByNameDesc

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }, "sort":[{"name":{"order":"desc"}}] }

实例

插入数据

  1. 每个文档必须独占一行,不能换行。
  2. 此命令要放到postman中去执行,如果用head执行会失败

http://localhost:9200/
POST _bulk

{"index":{"_index":"blog","_id":1}}
{"blogId":1,"title":"Spring Data ElasticSearch学习教程1","content":"这是批量添加的文档1","author":"Tony","category":"ElasticSearch","status":1,"serialNum":"1","createTime":"2021-10-10 11:52:01.249","updateTime":null}
{"index":{"_index":"blog","_id":2}}
{"blogId":2,"title":"Spring Data ElasticSearch学习教程2","content":"这是批量添加的文档2","author":"Tony","category":"ElasticSearch","status":1,"serialNum":"2","createTime":"2021-10-10 11:52:02.249","updateTime":null}
{"index":{"_index":"blog","_id":3}}
{"blogId":3,"title":"Spring Data ElasticSearch学习教程3","content":"这是批量添加的文档3","author":"Tony","category":"ElasticSearch","status":1,"serialNum":"3","createTime":"2021-10-10 11:52:03.249","updateTime":null}
{"index":{"_index":"blog","_id":4}}
{"blogId":4,"title":"Spring Data ElasticSearch学习教程4","content":"这是批量添加的文档4","author":"Tony","category":"ElasticSearch","status":1,"serialNum":"4","createTime":"2021-10-10 11:52:04.249","updateTime":null}
{"index":{"_index":"blog","_id":5}}
{"blogId":5,"title":"Spring Data ElasticSearch学习教程5","content":"这是批量添加的文档5","author":"Tony","category":"ElasticSearch","status":1,"serialNum":"5","createTime":"2021-10-10 11:52:05.249","updateTime":null}
{"index":{"_index":"blog","_id":6}}
{"blogId":6,"title":"Java学习教程6","content":"这是批量添加的文档6","author":"Tony","category":"ElasticSearch","status":1,"serialNum":"6","createTime":"2021-10-10 11:52:06.249","updateTime":null}
{"index":{"_index":"blog","_id":7}}
{"blogId":7,"title":"Java学习教程7","content":"这是批量添加的文档7","author":"Pepper","category":"ElasticSearch","status":1,"serialNum":"7","createTime":"2021-10-10 11:52:07.249","updateTime":null}
{"index":{"_index":"blog","_id":8}}
{"blogId":8,"title":"Java学习教程8","content":"这是批量添加的文档8","author":"Pepper","category":"ElasticSearch","status":1,"serialNum":"8","createTime":"2021-10-10 11:52:08.249","updateTime":null}
{"index":{"_index":"blog","_id":9}}
{"blogId":9,"title":"Java学习教程9","content":"这是批量添加的文档9","author":"Pepper","category":"ElasticSearch","status":1,"serialNum":"9","createTime":"2021-10-10 11:52:09.249","updateTime":null}
{"index":{"_index":"blog","_id":10}}
{"blogId":10,"title":"Java学习教程10","content":"这是批量添加的文档10","author":"Pepper","category":"ElasticSearch","status":1,"serialNum":"10","createTime":"2021-10-10 11:52:10.249","updateTime":null}

Repository

package com.example.demo.dao;

import com.example.demo.entity.Blog;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface BlogRepository extends ElasticsearchRepository {
    List findByTitle(String title);

    List findByTitleAndContent(String title, String content);

    Page findByTitleAndContent(String title, String content, Pageable pageable);
}

Controller

package com.example.demo.controller;

import com.example.demo.dao.BlogRepository;
import com.example.demo.entity.Blog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Api(tags = "自定义方法查询")
@RestController
@RequestMapping("customMethod")
public class CustomMethodController {
    @Autowired
    private BlogRepository blogRepository;

    @ApiOperation("通过标题和内容查询")
    @GetMapping("findByTitleAndContent")
    public void findByTitleAndContent(String title, String content) {
        List byTitleList = blogRepository.findByTitle(title);
        List byTitleAndContentList = blogRepository
                .findByTitleAndContent(title, content);

        PageRequest page = PageRequest.of(0, 2);
        Page byTitleAndContentPage = blogRepository.findByTitleAndContent(title, content, page);

        System.out.println("-----------------------------------------------");
        System.out.println("byTitleList:             " + byTitleList);
        System.out.println("byTitleAndContentList:   " + byTitleAndContentList);
        System.out.println("byTitleAndContentPage:   " + byTitleAndContentPage.getContent());
    }
}

测试1:标题不为空,内容不为空

前端参数

后端结果:

-----------------------------------------------
byTitleList:             [Blog(blogId=3, title=Spring Data ElasticSearch学习教程3, content=这是批量添加的文档3, author=Tony, category=ElasticSearch, status=1, serialNum=3, createTime=Sun Oct 10 19:52:03 CST 2021, updateTime=null), Blog(blogId=5, title=Spring Data ElasticSearch学习教程5, content=这是批量添加的文档5, author=Tony, category=ElasticSearch, status=1, serialNum=5, createTime=Sun Oct 10 19:52:05 CST 2021, updateTime=null), Blog(blogId=4, title=Spring Data ElasticSearch学习教程4, content=这是批量添加的文档4, author=Tony, category=ElasticSearch, status=1, serialNum=4, createTime=Sun Oct 10 19:52:04 CST 2021, updateTime=null), Blog(blogId=2, title=Spring Data ElasticSearch学习教程2, content=这是批量添加的文档2, author=Tony, category=ElasticSearch, status=1, serialNum=2, createTime=Sun Oct 10 19:52:02 CST 2021, updateTime=null), Blog(blogId=1, title=Spring Data ElasticSearch学习教程1, content=这是批量添加的文档1, author=Tony, category=ElasticSearch, status=1, serialNum=1, createTime=Sun Oct 10 19:52:01 CST 2021, updateTime=null)]
byTitleAndContentList:   [Blog(blogId=2, title=Spring Data ElasticSearch学习教程2, content=这是批量添加的文档2, author=Tony, category=ElasticSearch, status=1, serialNum=2, createTime=Sun Oct 10 19:52:02 CST 2021, updateTime=null)]
byTitleAndContentPage:   [Blog(blogId=2, title=Spring Data ElasticSearch学习教程2, content=这是批量添加的文档2, author=Tony, category=ElasticSearch, status=1, serialNum=2, createTime=Sun Oct 10 19:52:02 CST 2021, updateTime=null)]

测试2:标题不为空,内容为空

前端参数:

后端结果:

-----------------------------------------------
byTitleList:             [Blog(blogId=3, title=Spring Data ElasticSearch学习教程3, content=这是批量添加的文档3, author=Tony, category=ElasticSearch, status=1, serialNum=3, createTime=Sun Oct 10 19:52:03 CST 2021, updateTime=null), Blog(blogId=5, title=Spring Data ElasticSearch学习教程5, content=这是批量添加的文档5, author=Tony, category=ElasticSearch, status=1, serialNum=5, createTime=Sun Oct 10 19:52:05 CST 2021, updateTime=null), Blog(blogId=4, title=Spring Data ElasticSearch学习教程4, content=这是批量添加的文档4, author=Tony, category=ElasticSearch, status=1, serialNum=4, createTime=Sun Oct 10 19:52:04 CST 2021, updateTime=null), Blog(blogId=2, title=Spring Data ElasticSearch学习教程2, content=这是批量添加的文档2, author=Tony, category=ElasticSearch, status=1, serialNum=2, createTime=Sun Oct 10 19:52:02 CST 2021, updateTime=null), Blog(blogId=1, title=Spring Data ElasticSearch学习教程1, content=这是批量添加的文档1, author=Tony, category=ElasticSearch, status=1, serialNum=1, createTime=Sun Oct 10 19:52:01 CST 2021, updateTime=null)]
byTitleAndContentList:   []
byTitleAndContentPage:   []

可以看到,参数只有title的查询才查到了数据,另外两个需要两个参数的查询都没查到数据。

也就是说,自定义方法无法进行动态查询,就算是条件为空,也会放到查询条件中。

测试3:标题不为空,内容为空(但标题条件不是全单词)

前端参数

后端结果

-----------------------------------------------
byTitleList:             []
byTitleAndContentList:   []
byTitleAndContentPage:   []

原因: ElasticSearch是先将内容进行分词,然后再将这些分词创建索引的(即:可以通过分词搜到东西)。对于英文来说,单词就是最小的分词单位了,ES会通过空格、逗号等标点符号来把独立的单词作为分词。比如:“Data”,它就是一个单词,不会再对其进行拆分了,所以,搜整个单词才能搜到。

自定义DSL查询 简介

        跟JPA一样,Spring Data ElasticSearch可以使用@Query自定义语句进行查询。

        但Spring Data ElasticSearch不能通过冒号指定参数(比如:title),只能用问号加序号(比如?0)。

实例

Repository

package com.example.demo.dao;

import com.example.demo.entity.Blog;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface BlogRepository extends ElasticsearchRepository {
    // 这样写不行,查不到数据。原因待确定
    // @Query("{"bool":{"must":[{"match":{"title":":titleParam"}}," +
    //         "{"match":{"content":":contentParam"}}]}}")
    // List findByTitleAndContentCustom(@Param("titleParam") String title, @Param("contentParam") String content);

    @Query("{"bool":{"must":[{"match":{"title":"?0"}}," +
                                "{"match":{"content":"?1"}}]}}")
    List findByTitleAndContentCustom(@Param("title") String title, @Param("content") String content);

    @Query("{"bool":{"must":[{"match":{"title":"?0"}}," +
            "{"match":{"content":"?1"}}]}}")
    Page findByTitleAndContentCustom(@Param("title") String title, @Param("content") String content,
                                     Pageable pageable);
}

Controller

package com.example.demo.controller;

import com.example.demo.dao.BlogRepository;
import com.example.demo.entity.Blog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.License;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Api(tags = "自定义DSL查询")
@RestController
@RequestMapping("customDSL")
public class CustomDSLController {
    @Autowired
    private BlogRepository blogRepository;

    @ApiOperation("列表")
    @GetMapping("listByTitleAndContent")
    public List listByTitleAndContent(String title, String content) {
        return blogRepository.findByTitleAndContentCustom(title, content);
    }

    @ApiOperation("分页")
    @GetMapping("pageByTitleAndContent")
    public Page pageByTitleAndContent(String title, String content) {
        PageRequest pageRequest = PageRequest.of(0, 2);
        return blogRepository.findByTitleAndContentCustom(title, content, pageRequest);
    }
}

测试1:列表。标题不为空,内容不为空

测试2:列表。标题不为空,内容为空

结果:查不到东西。所以自定义DSL不能动态查询。

测试1:分页。标题不为空,内容不为空

其他网址

Elasticsearch、Spring Data Elasticsearch、Spring Boot版本对照表_旭东怪的博客-CSDN博客

SpringBoot-starter-data整合Elasticsearch_程序员小强的博客-CSDN博客

Elasticsearch(五):Spring Data Elasticsearch 操作索引_Gooooa的博客-CSDN博客

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317796.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号