Spring Boot笔记-Spring Boot与检索(十一)

1.检索

Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard的方式保证数据安全,并且提供自动resharding的功能,github等大型的站点也是采用了Elasticsearch作为其搜索服务。

2.概念

以员工信息存储为例,一个文档代表一个员工数据。存储到ElasticSearch的行为叫索引,在索引文档之前,需要确定文档存储的位置。一个ElasticSearch集群可以包含多个索引,每个索引可以包含多个类型,不同类型存储多个文档,每个文档有多个属性。

3.整合ElasticSearch测试

1.安装镜像

使用命令:docker pull elasticsearch:7.6.2下载镜像,不带tag会提示lastest找不到,所以就指定一个tag。

使用命令:docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 elasticsearch:7.6.2启动镜像。这里需要说一下,ElasticSearch启动,默认吃2G的内存,内存不够的可以带上-e参数加上内存限制。如果内存足够,可以不带-e参数,这里有两个-p,9200端口是web通信端口,9300是分布式ElasticSearch结点间通信端口。

启动之后,访问http://192.168.0.123:9200/,如果可以访问到,说明启动成功了,如果访问不到,说明启动失败了。

这里,我启动失败了,使用命令docker logs 容器id,查看报错信息,一共有两个。

ERROR: [2] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
[2]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
ERROR: Elasticsearch did not exit normally - check the logs at /usr/share/elasticsearch/logs/docker-cluster.log

第一个报错的意思是ElasticSearch拥有的内存太小,至少需要262144。使用命令sysctl -a|grep vm.max_map_count查看得到vm.max_map_count = 65530,我们需要修改这个值。单次生效的方法:sysctl -w vm.max_map_count=262144。要想永久生效,需要在/etc/sysctl.conf文件下添加一行:vm.max_map_count=262144并重启,即可解决。

第二个问题应该是高版本和低版本的不同,修改启动命令为:docker run -d -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:7.6.2,这里多了一个-e "discovery.type=single-node"参数,应该是以单结点方式启动的意思,避免集群检查。

再次访问http://192.168.0.123:9200/,可以看到信息,表示ElasticSearch启动成功。

2.功能测试

ElasticSearch中文文档地址:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

Elasticsearch是面向文档的,意味着它存储整个对象或文档。Elasticsearch不仅存储文档,而且索引每个文档的内容,使之可以被检索。在Elasticsearch中,我们对文档进行索引、检索、排序和过滤—​而不是对行列数据。这是一种完全不同的思考数据的方式,也是Elasticsearch能支持复杂全文检索的原因。

ElasticSearch使用JSON作为文档的序列化格式。

向ES中添加员工信息:

发送PUT请求到http://192.168.0.123:9200/megacorp/employee/1,携带的请求体是JSON格式的,url中的megacorp是索引名称,employee是类型名称,1是员工id。这里使用Postman来发送这个请求。

从ES中获取员工信息:

发送GET请求到http://192.168.0.123:9200/megacorp/employee/1即可拿到数据。

从ES中删除员工信息:

发送DELETE请求到http://192.168.0.123:9200/megacorp/employee/1即可删除数据。

查看ES中是否有员工信息:

发送HEAD请求到http://192.168.0.123:9200/megacorp/employee/1,如果返回200,表示有这个员工信息,如果返回404,表示没有这个员工信息。

修改ES中员工信息:

和新增一样,发送PUT请求即可。

查询全部信息:

发送GET请求到http://192.168.0.123:9200/megacorp/employee/_search即可。

按照条件查询:

比如,按照last_name属性查询,需要将q=last_name:Smith参数带到请求后面即可,发送GET请求到http://192.168.0.123:9200/megacorp/employee/_search?q=last_name:Smith

按照检索表达式查询:

更复杂的检索表达式:
{
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "last_name" : "smith" 
                }
            },
            "filter": {
                "range" : {
                    "age" : { "gt" : 30 } 
                }
            }
        }
    }
}

全文检索表达式:
{
    "query" : {
        "match" : {
            "about" : "rock climbing"
        }
    }
}

短语检索表达式:
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    }
}

高亮检索表达式:
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    },
    "highlight": {
        "fields" : {
            "about" : {}
        }
    }
}

3.Spring Boot整合ElasticSearch

新建Spring Boot项目,添加Spring Web、Spring Data ElasticSearch(Access+Driver)依赖。

Spring Boot默认支持两种技术和ES交互:Jest(现在已经@Deprecated了)和SpringData ElasticSearch。

SpringData ElasticSearch的自动配置类中会导入Client、ElasticSearchTemplate,还提供了ElasticSearchRepository的子接口操作ES。

加入yml配置文件。

spring:
  data:
    elasticsearch:
      # cluster-name的取值,要和浏览器访问192.168.0.123:9200的返回结果里的cluster-name一致
      cluster-name: docker-cluster
      cluster-nodes: 192.168.0.123:9300

观察左侧导入的org.elasticsearch:elasticsearch:6.8.7,这个6.8.7是spring-boot-starter-data-elasticsearch帮我们导入的,而我们镜像里的版本是7.6.2,ElasticSearch对版本要求比较严格,这里的版本不一致,后面会报错,所以需要将镜像换成6.8.7版本。

Spring Data ElasticSearch对应的ElasticSearch版本查询地址:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.0.RC3/reference/html/#preface.versions

Spring Data Elasticsearch导入的Elasticsearch versions
Spring Data ElasticSearchElasticSearch
3.2.x6.8.1
3.1.x6.2.2
3.0.x5.5.0
2.1.x2.4.0
2.0.x2.2.0
1.3.x1.5.2

回到虚拟机中,替换Docker镜像版本。

  1. 使用命令docker stop 容器id,停止容器。
  2. 使用命令docker rm 容器id,删除容器。
  3. 使用命令docker images查看所有镜像,后使用docker rmi 镜像id,删除ElasticSearch的镜像。
  4. 使用命令docker pull elasticsearch:6.8.7下载6.8.7版本的ElasticSearch镜像。
  5. 使用命令docker run -d -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:6.8.7创建并启动容器。
  6. 通过浏览器访问http://192.168.0.123:9200地址,确认版本号是不是6.8.7,以及容器是否正常启动。

创建bean以及repository,通过测试类进行测试。

package com.atguigu.elasticsearch.bean;

import org.springframework.data.elasticsearch.annotations.Document;

// indexName:索引名称 type:索引类型
@Document(indexName = "atguigu", type = "book")
public class Book {
    private int id;
    private String name;
    private String author;

    public Book() {
    }

    public Book(int id, String name, String author) {
        this.id = id;
        this.name = name;
        this.author = author;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }
}
package com.atguigu.elasticsearch.repository;

import com.atguigu.elasticsearch.bean.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface BookRepository extends ElasticsearchRepository<Book, Integer> {
    public List<Book> findByNameLike(String name);

    public List<Book> findByAuthorLike(String author);
}
package com.atguigu.elasticsearch;

import com.atguigu.elasticsearch.bean.Book;
import com.atguigu.elasticsearch.repository.BookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringBootElasticsearch03ApplicationTests {
    @Autowired
    BookRepository bookRepository;

    @Test
    void contextLoads() {
    }

    @Test
    public void index() {
        Book book = new Book();
        book.setId(1);
        book.setName("西游记");
        book.setAuthor("吴承恩");
        bookRepository.index(book);
    }

    @Test
    public void findByNameLike() {
        List<Book> bookList = bookRepository.findByNameLike("西");
        for (Book book : bookList) {
            System.out.println(book);
        }
    }
    
    @Test
    public void findByAuthorLike() {
        List<Book> bookList = bookRepository.findByAuthorLike("吴");
        for (Book book : bookList) {
            System.out.println(book);
        }
    }
}

运行index()方法,通过浏览器访问http://192.168.0.123:9200/atguigu/book/_search可以查看到全部索引数据,访问http://192.168.0.123:9200/atguigu/book/1可以看到刚才插入的id为1的索引数据。调用findByNameLike()方法可以以Like书名的方式查询到结果,但是我们只写了一个接口,并没有写实现,是如何实现的呢?

其实是根据方法名,构造查询表达式交给ES查询。上面的例子是按照name域模糊查询,所以方法名是findByNameLike(),如果要模糊查询author域,则方法名必须是findByAuthorLike(),字母大小写也不能错,否则,就会报错,或者查询结果不符合预期。

方法名和查询表达式的对应关系,参照这个地址了解一下:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.7.RELEASE/reference/html/#elasticsearch.repositories

另外,还支持@Query注解的方式标注Query表达式,标注在接口上,有点类似于Mybatis的注解形式。

另外,还有ElasticSearchTemplate的查询,可以构造更复杂的查询方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值