Spring Boot与检索
ElasticSearch
1. ElasticSearch简介
1)Java语言编写的开源全文搜索引擎。
2)用于快速的存储、搜索和分析海量数据。
3)是一个分布式搜索服务。
4)提供Restful API,通过发送请求的方式就可以将ElasticSearch用起来。
5)底层基于Lucene(开源的搜索引擎软件工具包)
2. Docker安装ElasticSearch
#这里安装的是5.6.13版本,安装8.2.0,通过相同的方式启动是失败的
docker pull elasticsearch:5.6.13
#web通信端口:9200
#分布式环境时各个节点之间通信的端口:9300
#初始的堆内存大小:-Xms256m,如果不指定,默认初始占用2G的堆内存空间
#最大使用的堆内存大小:-Xmx256m
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name ES02 3fd2f723b598
出现下面的界面就是安装成功了
3. Elasticsearch快速入门
官方文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
3.1 介绍
1)面向文档,存储整个对象或文档,方便对文档进行索引、检索、排序和过滤
2)使用JSON作为文档的序列化格式,使用JSON的好处是轻量级、跨平台
比如存储的user对象
{
"email": "[email protected]",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}
3.2 基本概念
1)索引(动词):给ElasticSearch中存储数据的行为就叫做索引,实际含义可以和存储划等号
2)索引(名词):一个 Elasticsearch 集群可以 包含多个 索引,类比Mysql中的数据库
3)类型:每个索引可以包含多个类型,类比Mysql中的数据表
4)文档:不同的类型存储着多个文档,类比Mysql中数据表的记录,每张表有多条记录,每个类型下有多个文档
5)属性:每个文档有多个属性,类比Mysql中记录的每个字段
3.3 基本操作
3.3.1 索引文档(C)
实际上就是将数据存储到ElasticSearch中
请求地址格式:ElasticSearch服务器地址:web端口/索引/类型/文档ID
如:http://192.168.37.128:9200/megacorp/employee/1
请求方式必须是PUT
3.3.2 检索文档(R)
请求地址格式不变,请求方式变为GET
3.3.3 更新文档(U)
再次索引文档即可,更新后version的值会增加
3.3.4 删除文档(D)
请求地址格式不变,请求方式变为DELETE
3.3.5 检查是否存在指定文档
检查ElasticSearch中是否存在指定的文档,根据响应结果中的Status判断
3.3.6 轻量搜索
请求地址格式:ElasticSearch服务器地址:web端口/索引/类型/_search[查询字符串]
其中查询字符串是可选的,如果不加查询字符串,默认查所有
如果携带查询字符串,按条件进行查询
如:http://192.168.37.128:9200/megacorp/employee/?q=last_name:Smith
查询所有文档中last_name字段的值为Smith的文档
请求方式必须是GET
3.3.7 查询表达式搜索
查询表达式:给ElasticSearch提交一串JSON表达式,JSON中指定查询规则
请求地址格式:ElasticSearch服务器地址:web端口/索引/类型/_search
请求体:
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
请求方式:POST
可以进行更复杂的查询,比如使用filter
只需要改变查询表达式即可
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
3.3.7 全文搜索
指定属性值进行查询,查询出文档中属性的属性值包含我们指定的属性值的文档
请求地址:ElasticSearch服务器地址:web端口/索引/类型/_search
请求体:
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
比如这里就要查文档的about属性包含rock climbing的文档,并不是绝对比配才能够查到,包含其中的一个单词,比如climbing也是能够查出来的,匹配程度可以通过响应中_score(相关性得分)的大小进行区分。
请求方式:GET
3.3.8 短语搜索
与全文搜索不同,短语搜索查询时会将查询条件中的属性值作为一个完整的单词进行精确匹配
请求地址:ElasticSearch服务器地址:web端口/索引/类型/_search
请求体:
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
请求方式:GET
3.3.9 高亮搜索
通过查询表达式中的highlight
参数结合短语搜索进行高亮搜索
请求地址:ElasticSearch服务器地址:web端口/索引/类型/_search
请求体:
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
请求方式:GET
4. SpringBoot整合Jest操作Elasticsearch
Jest:ElasticSearch客户端工具,通过HTTP方式与Elasticsearch交互。
SpringBoot默认支持两种技术来和ES交互:
1)Jest (默认不生效)
需要导入Jest的工具包(io.searchbox.client.JestClient)
2)SpringData ELasticSearch
4.1 引入依赖
引入依赖时需要注意Jest和Elasticsearch的版本对应关系
Jest和ES版本对应关系:Jest.x对应ES.x,比如,Es是5.x.x的,Jest也需要是5.x.x的
<!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>5.3.4</version>
</dependency>
4.2 自动配置
Jest对Elasticsearch的自动配置:org.springframework.boot.autoconfigure.elasticsearch
1)JestAutoConfiguration
向容器中放了JestClient,用来操作Elasticsearch
2)需要在全局配置中配置spring.elasticsearch.jest.uris
,默认是http://localhost:9200
4.3 全局配置
spring:
elasticsearch:
jest:
uris: http://192.168.37.128:9200
4.4 Jest操作Elasticsearch
JavaBean
public class Article {
//@JestId:标识这是一个主键
@JestId
private Integer id;
private String author;
private String title;
private String content;
//省略了get、set方法
...
}
@Autowired
JestClient jestClient;
/**
* 索引(存储)一个文档
*/
@Test
public void testJestClient(){
Article article = new Article();
article.setId(1);
article.setAuthor("zhangsan");
article.setTitle("好消息");
article.setContent("Hello world");
// 构建索引(存储)功能
// Builder(article):Builder的参数指定了存储哪个对象
// .index("atguigu").type("test"):指定了存储到哪个索引(名词)下的哪个类型,Id已经在Article中通过@JestId注解指定了,所以这里不需要再指定
Index index = new Index.Builder(article).index("atguigu").type("test").build();
try {
jestClient.execute(index);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 全文搜索
*/
@Test
public void testJestClient2(){
// 创建查询表达式,全文搜索content属性包含Hello值的文档
String json = "{\n" +
" \"query\" : {\n" +
" \"match\" : {\n" +
" \"content\" : \"Hello\"\n" +
" }\n" +
" }\n" +
"}";
// 构建搜索功能
// Builder(json):Builder的参数指定了查询表达式
// .addIndex("atguigu").addType("test"):指定了要查找哪个索引(名词)下的哪个类型下的文档
Search search = new Search.Builder(json).addIndex("atguigu").addType("test").build();
try {
SearchResult result = jestClient.execute(search);
System.out.println(result.getJsonString());
} catch (IOException e) {
e.printStackTrace();
}
}
5. SpringBoot整合SpringData Elasticsearch操作Elasticsearch
5.1 引入依赖
<!--SpringBoot默认使用SpringData ElasticSearch模块进行操作-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
5.2 自动配置
SpringData对Elasticsearch的自动配置:org.springframework.boot.autoconfigure.data.elasticsearch
1)ElasticsearchAutoConfiguration
向容器中放了Client
,需要配置节点信息(clusterNodes和clusterName),通过Client来操作Elasticsearch
2)ElasticsearchDataAutoConfiguration
向容器中放了ElasticsearchTemplate
,用来操作Elasticsearch
3)ElasticsearchRepositoriesAutoConfiguration
需要编写一个ElasticsearchRepository
的子接口来操作Elasticsearch,类似JPA的编程方式
5.3 全局配置
主配置文件中配置节点信息
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 192.168.37.128:9300
cluster-name
单节点的cluster-nodes就是ip+分布式环境时各个节点之间通信的端口
启动后报错,这是由于Spring Data Elasticsearch与Elasticsearch版本不适配造成的
Spring Data Elasticsearch与Elasticsearch版本适配如下图:
我的Spring Data Elasticsearch版本是
Elasticsearch版本是
版本不适配,处理方法有两种
1)升级SpringBoot版本,从而升级Spring Data Elasticsearch的版本
2)安装对应版本的Elasticsearch
我这里选择第二种方法,首先查看我的Spring Data Elasticsearch引入的Elasticsearch版本是多少
那么我就要安装2.4.6版本的Elasticsearch
重新启动,不再有报错,问题解决
5.4 创建ElasticsearchRepository的子接口操作Elasticsearch
编写一个ElasticsearchRepository的子接口
//两个泛型的值:要存取的数据类型,id的类型
public interface BookRepository extends ElasticsearchRepository<Book, Integer> {
}
JavaBean
//indexName = "atguigu":指定要存储到哪个索引
//type = "book":指定要存储到哪个类型
//文档id不需要单独指定,因为在book对象中已经传入了id
@Document(indexName = "atguigu", type = "book")
public class Book {
private Integer id;
private String author;
private String title;
//省略了get、set、toString方法
...
}
@Autowired
BookRepository repository;
//测试索引一个文档
@Test
public void test01(){
Book book = new Book();
book.setId(15);
book.setAuthor("lisidasdd");
book.setTitle("wainasdsfi");
repository.index(book);
}
ElasticsearchRepository已经内置了很多的方法操作Elasticsearch,同时也支持自定义方法,但是方法名必须按照要求来
首先在子接口中定义方法
public interface BookRepository extends ElasticsearchRepository<Book, Integer> {
public List<Book> findByTitleLike(String bookName);
}
@Autowired
BookRepository repository;
@Test
public void test01(){
for (Book book : repository.findByTitleLike("wai")) {
System.out.println(book);
}
;
}
ElasticsearchRepository支持的自定义方法名和对应的查询表达式如下
Keyword | Sample | Elasticsearch Query String |
---|---|---|
And |
findByNameAndPrice |
{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} |
Or |
findByNameOrPrice |
{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} |
Is |
findByName |
{"bool" : {"must" : {"field" : {"name" : "?"}}}} |
Not |
findByNameNot |
{"bool" : {"must_not" : {"field" : {"name" : "?"}}}} |
Between |
findByPriceBetween |
{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
LessThanEqual |
findByPriceLessThan |
{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
GreaterThanEqual |
findByPriceGreaterThan |
{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} |
Before |
findByPriceBefore |
{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
After |
findByPriceAfter |
{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} |
Like |
findByNameLike |
{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}} |
StartingWith |
findByNameStartingWith |
{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}} |
EndingWith |
findByNameEndingWith |
{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}} |
Contains/Containing |
findByNameContaining |
{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}} |
In |
findByNameIn(Collection<String>names) |
{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}} |
NotIn |
findByNameNotIn(Collection<String>names) |
{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}} |
Near |
findByStoreNear |
Not Supported Yet ! |
True |
findByAvailableTrue |
{"bool" : {"must" : {"field" : {"available" : true}}}} |
False |
findByAvailableFalse |
{"bool" : {"must" : {"field" : {"available" : false}}}} |
OrderBy |
findByAvailableTrueOrderByNameDesc |
{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}} |
同时也支持自己设定执行的查询表达式
标签:SpringBoot,1x,Boot,must,文档,Elasticsearch,bool,true,name From: https://www.cnblogs.com/wzzzj/p/18039119