Elasticsearch搜索引擎安装使用及Java中使用
Elasticsearch(一)Docker搭建ES集群
关闭防火墙
后面我们要使用多个端口,为了避免繁琐的开放端口操作,我们关掉防火墙
# 关闭防火墙
systemctl stop firewalld.service# 禁用防火墙
systemctl disable firewalld.service
安装Docker
我们使用 Docker 来运行 Elasticsearch,首先安装 Docker
下载 Elastic Search 镜像
docker pull elasticsearch:7.9.3
集群部署结构
在一台服务器上,使用Docker部署三个ES容器组成的集群
准备虚拟网络和挂载目录
# 创建虚拟网络
docker network create es-net# node1 的挂载目录
mkdir -p -m 777 /var/lib/es/node1/plugins
mkdir -p -m 777 /var/lib/es/node1/data# node2 的挂载目录
mkdir -p -m 777 /var/lib/es/node2/plugins
mkdir -p -m 777 /var/lib/es/node2/data# node3 的挂载目录
mkdir -p -m 777 /var/lib/es/node3/plugins
mkdir -p -m 777 /var/lib/es/node3/data
设置 max_map_count
必须修改系统参数 max_map_count
,否则 Elasticsearch 无法启动:
在 /etc/sysctl.conf
文件中添加 vm.max_map_count=262144
echo 'vm.max_map_count=262144' >>/etc/sysctl.conf
需要重启服务器!
确认参数配置:
cat /etc/sysctl.conf
启动 Elasticsearch 集群
node1:
docker run -d \--name=node1 \--restart=always \--net es-net \-p 9200:9200 \-p 9300:9300 \-v /var/lib/es/node1/plugins:/usr/share/elasticsearch/plugins \-v /var/lib/es/node1/data:/usr/share/elasticsearch/data \-e node.name=node1 \-e node.master=true \-e network.host=node1 \-e discovery.seed_hosts=node1,node2,node3 \-e cluster.initial_master_nodes=node1 \-e cluster.name=es-cluster \-e "ES_JAVA_OPTS=-Xms256m -Xmx256m" \elasticsearch:7.9.3
环境变量说明:
环境变量 说明
node.name 节点在集群中的唯一名称
node.master 可已被选举为主节点
network.host 当前节点的地址
discovery.seed_hosts 集群中其他节点的地址列表
cluster.initial_master_nodes 候选的主节点地址列表
cluster.name 集群名
ES_JAVA_OPTS java虚拟机参数
参考 Networking | Elasticsearch Guide [8.1] | Elastic
node2:
docker run -d \--name=node2 \--restart=always \--net es-net \-p 9201:9200 \-p 9301:9300 \-v /var/lib/es/node2/plugins:/usr/share/elasticsearch/plugins \-v /var/lib/es/node2/data:/usr/share/elasticsearch/data \-e node.name=node2 \-e node.master=true \-e network.host=node2 \-e discovery.seed_hosts=node1,node2,node3 \-e cluster.initial_master_nodes=node1 \-e cluster.name=es-cluster \-e "ES_JAVA_OPTS=-Xms256m -Xmx256m" \elasticsearch:7.9.3
node3:
docker run -d \--name=node3 \--restart=always \--net es-net \-p 9202:9200 \-p 9302:9300 \-v /var/lib/es/node3/plugins:/usr/share/elasticsearch/plugins \-v /var/lib/es/node3/data:/usr/share/elasticsearch/data \-e node.name=node3 \-e node.master=true \-e network.host=node3 \-e discovery.seed_hosts=node1,node2,node3 \-e cluster.initial_master_nodes=node1 \-e cluster.name=es-cluster \-e "ES_JAVA_OPTS=-Xms256m -Xmx256m" \elasticsearch:7.9.3
查看启动结果结果
http://192.168.64.181:9200
http://192.168.64.181:9200/_cat/nodes
chrome浏览器插件:elasticsearch-head
elasticsearch-head 项目提供了一个直观的界面,可以很方便地查看集群、分片、数据等等。elasticsearch-head最简单的安装方式是作为 chrome 浏览器插件进行安装。
在 elasticsearch-head 项目仓库中下载 chrome 浏览器插件
https://github.com/mobz/elasticsearch-head/raw/master/crx/es-head.crx
将文件后缀改为 zip
解压缩
在 chrome 浏览器中选择“更多工具”–“扩展程序”
在“扩展程序”中确认开启了“开发者模式”
点击“加载已解压的扩展程序”
选择前面解压的插件目录
在浏览器中点击 elasticsearch-head 插件打开 head 界面,并连接 http://192.168.64.181:9200/
Elasticsearch(二)IK中文分词器
安装 ik 分词器
从 ik 分词器项目仓库中下载 ik 分词器安装包,下载的版本需要与 Elasticsearch 版本匹配:
GitHub - medcl/elasticsearch-analysis-ik: The IK Analysis plugin integrates Lucene IK analyzer into elasticsearch, support customized dictionary.
或者可以访问 gitee 镜像仓库:
Gitee 极速下载/elasticsearch-analysis-ik
下载 elasticsearch-analysis-ik-7.9.3.zip
复制到 /root/
目录下
在三个节点上安装 ik 分词器
cd ~/# 复制 ik 分词器到三个 es 容器
docker cp elasticsearch-analysis-ik-7.9.3.zip node1:/root/
docker cp elasticsearch-analysis-ik-7.9.3.zip node2:/root/
docker cp elasticsearch-analysis-ik-7.9.3.zip node3:/root/# 在 node1 中安装 ik 分词器
docker exec -it node1 elasticsearch-plugin install file:///root/elasticsearch-analysis-ik-7.9.3.zip# 在 node2 中安装 ik 分词器
docker exec -it node2 elasticsearch-plugin install file:///root/elasticsearch-analysis-ik-7.9.3.zip# 在 node3 中安装 ik 分词器
docker exec -it node3 elasticsearch-plugin install file:///root/elasticsearch-analysis-ik-7.9.3.zip# 重启三个 es 容器
docker restart node1 node2 node3
查看安装结果
在浏览器中访问 http://192.168.64.181:9200/_cat/plugins
如果插件不可用,可以卸载后重新安装:
docker exec -it node1 elasticsearch-plugin remove analysis-ikdocker exec -it node2 elasticsearch-plugin remove analysis-ikdocker exec -it node3 elasticsearch-plugin remove analysis-ik
ik分词测试
ik分词器提供两种分词器: ik_max_word
和 ik_smart
ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;
ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。
ik_max_word
分词测试
使用 head 执行下面测试:
向 http://192.168.64.181:9200/_analyze
路径提交 POST
请求,并在协议体中提交 Json 数据:
{"analyzer":"ik_max_word","text":"中华人民共和国国歌"
}
ik_smart
分词测试
使用 head 执行下面测试:
向 http://192.168.64.181:9200/_analyze
路径提交 POST
请求,并在协议体中提交 Json 数据:
{"analyzer":"ik_smart","text":"中华人民共和国国歌"
}
Elasticsearch(三)使用 Kibana 操作 ES
下载 Kibana 镜像
docker pull kibana:7.9.3
启动 Kibana 容器
docker run \
-d \
--name kibana \
--net es-net \
-p 5601:5601 \
-e ELASTICSEARCH_HOSTS='["http://node1:9200","http://node2:9200","http://node3:9200"]' \
--restart=always \
kibana:7.9.3
启动后,浏览器访问 Kibana,进入 Dev Tools
:
http://192.168.64.181:5601/
索引、分片和副本
索引
Elasticsearch索引用来存储我们要搜索的数据,以倒排索引结构进行存储。
例如,要搜索商品数据,可以创建一个商品数据的索引,其中存储着所有商品的数据,供我们进行搜索:
当索引中存储了大量数据时,大量的磁盘io操作会降低整体搜索新能,这时需要对数据进行分片存储。
索引分片
在一个索引中存储大量数据会造成性能下降,这时可以对数据进行分片存储。
每个节点上都创建一个索引分片,把数据分散存放到多个节点的索引分片上,减少每个分片的数据量来提高io性能:
每个分片都是一个独立的索引,数据分散存放在多个分片中,也就是说,每个分片中存储的都是不同的数据。搜索时会同时搜索多个分片,并将搜索结果进行汇总。
索引副本
对分片创建多个副本,那么即使一个节点宕机,其他节点中的副本分片还可以继续工作,不会造成数据不可用:
创建索引
我们有三个节点,在每个节点上都创建一个分片。每个分片在另两个节点上各创建一个副本。
# 创建索引,命名为 products
PUT /products
{"settings": {"number_of_shards": 3, "number_of_replicas": 2}
}
映射(数据结构)
类似于数据库表结构,索引数据也被分为多个数据字段,并且需要设置数据类型和其他属性。
字段的数据类型
数字类型:
- byte、short、integer、long
- float、double
- unsigned_long
字符串类型:
- text : 会进行分词
- keyword : 不会进行分词,适用于email、主机地址、邮编等
日期和时间类型:
- date
类型参考:
Field data types | Elasticsearch Guide [8.1] | Elastic
创建映射
在 products 索引中创建映射。
分词器设置:
analyzer
:在索引中添加文档时,text类型通过指定的分词器分词后,再插入倒排索引search_analyzer
:使用关键词检索时,使用指定的分词器对关键词进行分词
查询时,关键词优先使用 search_analyzer
设置的分词器,如果 search_analyzer
不存在则使用 analyzer
分词器。
# 定义mapping,数据结构
PUT /products/_mapping
{"properties": {"id": {"type": "long"},"title": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"},"category": {"type": "text","analyzer": "ik_smart","search_analyzer": "ik_smart"},"price": {"type": "float"},"city": {"type": "text","analyzer": "ik_smart","search_analyzer": "ik_smart"},"barcode": {"type": "keyword"}}
}
映射参考:
Mapping | Elasticsearch Guide [8.1] | Elastic
查看映射
GET /products/_mapping
添加文档
添加的文档会有一个名为_id
的文档id,这个文档id可以自动生成,也可以手动指定,通常可以使用数据的id作为文档id。
# 添加文档
PUT /products/_doc/10033
{"id":"10033","title":"SONOS PLAY:5(gen2) 新一代PLAY:5无线智能音响系统 WiFi音箱家庭,潮酷数码会场","category":"潮酷数码会场","price":"3980.01","city":"上海","barcode":"527848718459"
}PUT /products/_doc/10034
{"id":"10034","title":"天猫魔盒 M13网络电视机顶盒 高清电视盒子wifi 64位硬盘播放器","category":"潮酷数码会场","price":"398.00","city":"浙江杭州","barcode":"522994634119"
}PUT /products/_doc/10035
{"id":"10035","title":"BOSE SoundSport耳塞式运动耳机 重低音入耳式防脱降噪音乐耳机","category":"潮酷数码会场","price":"860.00","city":"浙江杭州","barcode":"526558749068"
}PUT /products/_doc/10036
{"id":"10036","title":"【送支架】Beats studio Wireless 2.0无线蓝牙录音师头戴式耳机","category":"潮酷数码会场","price":"2889.00","city":"上海","barcode":"37147009748"
}PUT /products/_doc/10037
{"id":"10037","title":"SONOS PLAY:1无线智能音响系统 美国原创WiFi连接 家庭桌面音箱","category":"潮酷数码会场","price":"1580.01","city":"上海","barcode":"527783392239"
}
也可以自动生成 _id
值:
POST /products/_doc
{"id":"10027","title":"vivo X9前置双摄全网通4G美颜自拍超薄智能手机大屏vivox9","category":"手机会场","price":"2798.00","city":"广东东莞","barcode":"541396973568"
}
查看文档:
GET /products/_doc/10037
查看指定文档title字段的分词结果:
GET /products/_doc/10037/_termvectors?fields=title
修改文档
底层索引数据无法修改,修改数据实际上是先删除再重新添加。
两种修改方式:
- PUT:对文档进行完整的替换
- POST:可以修改一部分字段
修改价格字段的值:
# 修改文档 - 替换
PUT /products/_doc/10037
{"id":"10037","title":"SONOS PLAY:1无线智能音响系统 美国原创WiFi连接 家庭桌面音箱","category":"潮酷数码会场","price":"9999.99","city":"上海","barcode":"527783392239"
}
查看文档:
GET /products/_doc/10037
修改价格和城市字段的值:
# 修改文档 - 更新部分字段
POST /products/_update/10037
{"doc": {"price":"8888.88","city":"深圳"}
}
查看文档:
GET /products/_doc/10037
删除文档
DELETE /products/_doc/10037
清空
POST /products/_delete_by_query
{"query": {"match_all": {}}
}
删除索引
# 删除 products 索引
DELETE /products
可以尝试用不同的分片和副本值来重新创建 products 索引
Elasticsearch(四)搜索
导入测试数据
为了测试搜索功能,我们首先导入测试数据,3160条商品数据,数据样例如下:
{ "index": {"_index": "pditems", "_id": "536563"}}
{ "id":"536563","brand":"联想","title":"联想(Lenovo)小新Air13 Pro 13.3英寸14.8mm超轻薄笔记本电脑","sell_point":"清仓!仅北京,武汉仓有货!","price":"6688.0","barcode":"","image":"/images/server/images/portal/air13/little4.jpg","cid":"163","status":"1","created":"2015-03-08 21:33:18","updated":"2015-04-11 20:38:38"}
下载测试数据
Elasticsearch测试数据,3160条商品数据_elasticsearch测试数据-Java文档类资源-CSDN下载
将压缩文件中的 pditems.json
上传到服务器
创建索引和映射
PUT /pditems
{"settings": {"number_of_shards": 3, "number_of_replicas": 2},"mappings": {"properties": {"id": {"type": "long"},"brand": {"type": "text","analyzer": "ik_smart"},"title": {"type": "text","analyzer": "ik_max_word"},"sell_point": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"},"price": {"type": "float"},"image": {"type": "keyword"},"cid": {"type": "long"},"status": {"type": "byte"},"created": {"type": "date","format": "yyyy-MM-dd HH:mm:ss"},"updated": {"type": "date","format": "yyyy-MM-dd HH:mm:ss"}} }
}
用 head 查看索引:
导入数据
在服务器上,进入 pditems.json
所在的文件夹,执行批量数据导入:
curl -XPOST 'localhost:9200/pditems/_bulk' \-H 'Content-Type:application/json' \--data-binary @pditems.json
查看数据
搜索 pditems
索引中全部 3160 条数据:
GET /pditems/_search
{"query": {"match_all": {}},"size": 3160
}
搜索文档
搜索所有数据
# 搜索 pditems 索引中全部数据
POST /pditems/_search
{"query": {"match_all": {}}
}
关键词搜索
# 查询 pditems 索引中title中包含"电脑"的商品
POST /pditems/_search
{"query": {"match": {"title": "电脑"}}
}
搜索结果过滤器
# 价格大于2000,并且title中包含"电脑"的商品
POST /pditems/_search
{"query": {"bool": {"must": [{"match": {"title": "电脑"}}],"filter": [{"range": {"price": {"gte": "2000"}}}]}}
}
搜索结果高亮显示
POST /pditems/_search
{"query": {"multi_match":{"query": "手机","fields": ["title", "sell_point"]}},"highlight" : {"pre_tags" : ["<i class=\"highlight\">"],"post_tags" : ["</i>"],"fields" : {"title" : {},"sell_point" : {"pre_tags": "<em>","post_tags": "</em>"}}}
}
Elasticsearch(五)Spring Data Elasticsearch - 增删改查API
Spring Data Elasticsearch
Spring Data Elasticsearch - Reference Documentation
Spring Data Elasticsearch 是 Elasticsearch 搜索引擎开发的解决方案。它提供:
模板对象,用于存储、搜索、排序文档和构建聚合的高级API。
例如,Repository
使开发者能够通过定义具有自定义方法名称的接口来表达查询。
案例说明
在 Elasticsearch 中存储学生数据,并对学生数据进行搜索测试。
数据结构:
学号 | 姓名 | 性别 | 出生日期 |
---|---|---|---|
27 | 张三 | 男 | 2020-12-4 |
案例测试以下数据操作:
- 创建 students 索引和映射
- C - 创建学生数据
- R - 访问学生数据
- U - 修改学生数据
- D - 删除学生数据
- 使用 Repository 和 Criteria 搜索学生数据
创建项目
新建工程
2 新建 springboot module,添加 spring data elasticsearch 依赖
项目的 pom.xml 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>cn.tedu</groupId><artifactId>es-springboot</artifactId><version>0.0.1-SNAPSHOT</version><name>es-springboot</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
application.yml 配置
logging.level.tracer=TRACE
作用是在控制台中显示底层的查询日志
spring:elasticsearch:rest:uris: http://192.168.64.181:9200logging:level:tracer: TRACE
Student 实体类
package cn.tedu.esspringboot.es;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
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;@Document(indexName = "students",shards = 3,replicas = 2)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {@Idprivate Long id;@Field(analyzer = "ngram",type = FieldType.Text)private String name;@Field(type = FieldType.Keyword)private Character gender;@Field(type= FieldType.Date,format = DateFormat.custom,pattern = "yyyy-M-d")private String birthDate;
}
@Document 注解
@Documnet注解对索引的参数进行设置。
上面代码中,把 students 索引的分片数设置为3,副本数设置为2。
@Id 注解
在 Elasticsearch 中创建文档时,使用 @Id 注解的字段作为文档的 _id
值
@Field 注解
通过 @Field 注解设置字段的数据类型和其他属性。
文本类型 text 和 keyword
text 类型会进行分词。
keyword 不会分词。
analyzer 指定分词器
通过 analyzer 设置可以指定分词器,例如 ik_smart、ik_max_word 等。
我们这个例子中,对学生姓名字段使用的分词器是 ngram 分词器,其分词效果如下面例子所示:
字符串 | 分词结果 |
---|---|
刘德华 |
刘 刘德 刘德华 德 德华 华 |
通过 ElasticsearchRepository 实现 CRUD 操作
Spring Data 的 Repository 接口提供了一种声明式的数据操作规范,无序编写任何代码,只需遵循 Spring Data 的方法定义规范即可完成数据的 CRUD 操作。
ElasticsearchRepository 继承自 Repository,其中已经预定义了基本的 CURD 方法,我们可以通过继承 ElasticsearchRepository,添加自定义的数据操作方法。
Repository 方法命名规范
自定义数据操作方法需要遵循 Repository 规范,示例如下:
关键词 方法名 es查询
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”}}] }
StudentRepository
package cn.tedu.esspringboot.es;import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;public interface StudentRepository extends ElasticsearchRepository<Student, Long> {List<Student> findByName(String name);List<Student> findByNameOrBirthDate(String name, String birthDate);
}
业务类 StudentService
package cn.tedu.esspringboot.es;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class StudentService {@Autowiredprivate StudentRepository studentRepo;public void save(Student student) {studentRepo.save(student);}public void delete(Long id) {studentRepo.deleteById(id);}public void update(Student student) {save(student);}public List<Student> findByName(String name) {return studentRepo.findByName(name);}public List<Student> findByNameOrBirthDate(String name, String birthDate) {return studentRepo.findByNameOrBirthDate(name, birthDate);}
}
在 Elasticsearch 中创建 students 索引
在开始运行测试之前,在 Elasticsearch 中先创建 students 索引:
PUT /students
{"settings": {"number_of_shards": 3,"number_of_replicas": 2,"index.max_ngram_diff":30,"analysis": {"analyzer": {"ngram_analyzer": {"tokenizer": "ngram_tokenizer"}},"tokenizer": {"ngram_tokenizer": {"type": "ngram","min_gram": 1,"max_gram": 30,"token_chars": ["letter","digit"]}}}},"mappings": {"properties": {"id": {"type": "long"},"name": {"type": "text","analyzer": "ngram_analyzer"},"gender": {"type": "keyword"},"birthDate": {"type": "date","format": "yyyy-MM-dd"}}}
}
测试学生数据的 CRUD 操作
添加测试类,对学生数据进行 CRUD 测试
package cn.tedu.esspringboot;import cn.tedu.esspringboot.es.Student;
import cn.tedu.esspringboot.es.StudentService;
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
public class Test1 {@Autowiredprivate StudentService studentService;@Testpublic void test1() {studentService.save(new Student(998L,"张三",'男',"2020-12-04"));}@Testpublic void test2() {studentService.update(new Student(1L,"李四",'女',"2020-12-04"));}@Testpublic void test3() {List<Student> stu = studentService.findByName("四");System.out.println(stu);}@Testpublic void test4() throws Exception {List<Student> stu;stu = studentService.findByNameOrBirthDate("四", "1999-09-09");System.out.println(stu);stu = studentService.findByNameOrBirthDate("SFSDFS", "2020-12-04");System.out.println(stu);}
}
依次运行每个测试方法,并使用 head 观察测试结果
使用 Criteria 构建查询
Spring Data Elasticsearch 中,可以使用 SearchOperations 工具执行一些更复杂的查询,这些查询操作接收一个 Query 对象封装的查询操作。
Spring Data Elasticsearch 中的 Query 有三种:
- CriteriaQuery
- StringQuery
- NativeSearchQuery
多数情况下,CriteriaQuery 都可以满足我们的查询求。下面来看两个 Criteria 查询示例:
StudentSearcher
package cn.tedu.esspringboot.es;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.stream.Collectors;@Component
public class StudentSearcher {@Autowiredprivate ElasticsearchOperations searchOperations;public List<Student> searchByBirthDate(String birthDate) {Criteria c = new Criteria("birthDate").is(birthDate);return criteriaSearch(c);}public List<Student> searchByBirthDate(String ge, String le) {Criteria c = new Criteria("birthDate").between(ge, le);return criteriaSearch(c);}private List<Student> criteriaSearch(Criteria c) {CriteriaQuery q = new CriteriaQuery(c);SearchHits<Student> hits = searchOperations.search(q, Student.class);List<Student> list = hits.stream().map(SearchHit::getContent).collect(Collectors.toList());return list;}
}
修改 StudentService
在 StudentService 中,调用 StudentSearcher,执行查询:
package cn.tedu.esspringboot.es;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class StudentService {@Autowiredprivate StudentRepository studentRepo;@Autowiredprivate StudentSearcher studentSearcher;public void save(Student student) {studentRepo.save(student);}public void delete(Long id) {studentRepo.deleteById(id);}public void update(Student student) {save(student);}public List<Student> findByName(String name) {return studentRepo.findByName(name);}public List<Student> findByNameOrBirthDate(String name, String birthDate) {return studentRepo.findByNameOrBirthDate(name, birthDate);}public List<Student> findByBirthDate(String birthDate) {return studentSearcher.searchByBirthDate(birthDate);}public List<Student> findByBirthDate(String ge, String le) {return studentSearcher.searchByBirthDate(ge, le);}
}
在测试类中添加测试方法
package cn.tedu.esspringboot;import cn.tedu.esspringboot.es.Student;
import cn.tedu.esspringboot.es.StudentService;
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
public class Test1 {@Autowiredprivate StudentService studentService;@Testpublic void test1() {studentService.save(new Student(998L,"张三",'男',"2020-12-04"));}@Testpublic void test2() {studentService.update(new Student(1L,"李四",'女',"2020-12-04"));}@Testpublic void test3() {List<Student> stu = studentService.findByName("四");System.out.println(stu);}@Testpublic void test4() throws Exception {List<Student> stu;stu = studentService.findByNameOrBirthDate("四", "1999-09-09");System.out.println(stu);stu = studentService.findByNameOrBirthDate("SFSDFS", "2020-12-04");System.out.println(stu);}@Testpublic void test5() throws Exception {List<Student> stu;stu = studentService.findByBirthDate("2020-12-04");System.out.println(stu);}@Testpublic void test6() throws Exception {List<Student> stu;stu = studentService.findByBirthDate("2020-12-05", "2020-12-09");System.out.println(stu);}
}
Elasticsearch搜索引擎安装使用及Java中使用相关推荐
- ElasticSearch搜索引擎详解-持续更新中
ElasticSearch搜索引擎详解 1. ElasticSearch概述 1.1 elasticsearch是什么 1.2 全文搜索引擎 1.3 elasticsearch and solr 1. ...
- ffmpeg安装及在java中的使用案例
目录 前言 什么是ffmpeg? Windows下载及安装 后台代码 测试上传及播放 总结 前言 在开发中,经常有项目页面需要播放视频,也经常会有视频的容量很大,上次客户需要在页面上播放他们公司的宣传 ...
- ES(elasticsearch)搜索引擎安装和使用
本文章为转载文章,如要转载标注出处 查看全文 http://www.taodudu.cc/news/show-3144290.html 相关文章: VT高级搜索语法 hive模糊搜索表 击溃360手机 ...
- ElasticSerach安装IK中文分词器,并在Java中使用
1.所有文章优先发表在个人博客上: https://www.xdx97.com 2.后续如果有修改的话,可能忘记更新到CSDN了,给你带来不便,抱歉. 3.个人博客本篇文章地址 : https://w ...
- ElasticSearch在Java中的使用
前言 ElasticSearch在Java中使用,在此感谢狂神老师,狂神大神ES课程 提示:以下是本篇文章正文内容,下面案例可供参考 一.ElasticSearch-head可视化界面安装 下载并且解 ...
- elasticsearch搜索引擎下载安装
import com.yuepu.common.core.domain.BaseEntity; import lombok.Data;import java.util.Date; import jav ...
- elasticsearch搜索引擎查询java工具类
Elasticsearch查询java工具类 项目组使用Elasticsearch搜索引擎也有一段时间了,刚开始是2.4版本,现在又要在新的工程中使用,准备升级为5.4版本,以前的工具类也不好用了,没 ...
- java中git使用教程_【教程】Git在Eclipse中的安装和基本使用
一.安装 点击 Help->Install New Software->add 安装地址为:http://download.eclipse.org/egit/updates/ 选择插件 点 ...
- java安装_快速提示:Java中的ISO 8601持续时间
java安装 许多开发人员都知道ISO 8601定义的日期和时间的交换格式. (例如2007-08-31T16:47 +00:00代表2007年8月31日UTC的16:47 ) 但是,并不是很知名(至 ...
- 在Ubuntu中安装及配置java
描述:在Ubuntu16.04中配置jdk1.8 1. 下载jdk 下载地址:Java SE Development Kit 8 - Downloads - jdk8u301 (oracle.com) ...
最新文章
- DNS-sly:利用网络复杂性躲避审查
- vnc远程无法关闭窗口_无法启动远程桌面服务(VNC)[关闭]
- python中align_Python中如何自动化对齐?
- Hibernate 中的DetachedCriteria。
- POJ 2299 - Ultra-QuickSort BIT
- python权重初始值设置_pytorch自定义初始化权重的方法
- pythonwindow程序窗体操作_python操作Windows窗口程序
- php获取2次跳转之后的网址,爬虫:获取多次跳转后的页面url
- 蓝桥杯 算法提高 奥运会开幕式 deque
- acer软件保护卡怎么解除_外观精致性能强,配置丰富重量轻、宏碁(Acer)墨舞EX214轻薄笔记本 深度评测...
- 乌镇互联网大会:马化腾强势宣布,明年将推“VR微信”
- html好看的侧滑效果,H5 - 侧滑效果实现
- 服务器错误数字(代码)对照表
- openinstall与太平洋汽车达成合作
- 电竞英雄联盟数据API接口 - 【英雄联赛统计】API调用示例代码
- 数据结构——图书管理系统
- 测U盘实际容量 (缩水U盘、扩容盘、假U盘)
- 英雄联盟手游 lol手游内测资格申请,教大家申请体验资格
- 视频教程-C#LINQ查询技术-C#
- PI控制器的Matlab代码
热门文章
- html js点击下拉菜单代码,JavaScript下拉菜单功能实例代码
- 看漫画与动漫选他们吧,两款多源怪,再也不愁找不到了
- ITK VKT 安装-详细
- iMindMap手绘思维导图软件免费版
- 一份ERP系统总体解决方案
- cs透视源码c语言,CS--GO透视自瞄C++源码 CSGO C++源代码 参考学习!!!(CSGO C++ source code) - 下载 - 搜珍网...
- 汇编dos系统调用(输入输出篇)
- smartPrinter 安装时1722错误
- OFFICE文档转换到PDF的几种方法与转换效率和性能的简单比较
- 网优测试软件苹果手机,手机端网优测试软件详细介绍