目录
【*】什么是ElasticSerch?
ES是基于Lucene开发的分布式全文检索引擎,它可以存储整个对象或文档,索引(index)每个文档的内容使之可以被搜索
【*】设置ES跨域访问
elasticsearch配置文件:config/elasticsearch.yml,最末尾增加以下两句命令:
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE
http.cors.allow-headers: "X-Requested-With, Content-Type, Content-Length, X-User"
【*】启动ES相关信息
-
点击ElasticSearch下的bin目录下的elasticsearch.bat启动,要求jdk最少1.8
-
9300是tcp通讯端口,集群间和TCPClient都执行该端口,9200是http协议的RESTful接口 。
-
在浏览器上输入 http://localhost:9200/
-
可以通过安装ElasticSearch的head插件,完成图形化界面的效 果,完成索引数据的查看
-
elasticsearch-5-*以上版本安装head需要安装node和grunt
-
可以通过安装ElasticSearch的head插件,完成图形化界面的效 果,完成索引数据的查看
-
安装nodeJS:安装之后windows输入 node -v 查看版本号,查询到证明安装成功
-
安装Grunt:是基于Node.js的项目构建工具 在cmd控制台中输入如下执行命令
npm install -g grunt -cli
- 在elasticsearch-head-master目录下启动cmd命令
npm install
- 在elasticsearch-head-master目录下启动cmd命令
grunt server
【*】Elasticsearch核心概念
- 索引 index相当于Mysql中的数据库
- 类型 type相当于Mysql中的表
- 文档 document相当于Mysql中的表张的行(一条记录)
- 字段Field相当于Mysql中的列
- 映射 mapping(相当于数据库中表结构的定义)
- 接近实时 NRT
实时搜索
- 集群 cluster
- 节点 node,一个节点就是集群中的一台服务器
- 分片和复制 shards&replicas
- 分片:将索引进行分片,所有的分片加起来就是整个索引库
- 复制:每一篇都有一个备份
- 可以解决高可用、负载均衡的问题
【*】使用PostMan
-
1.添加索引库并设置其中的内容,为json形式
- 复制的时候把注释删掉,不然报错
{
"mappings":{//定义索引库中内容的结构
"article": {//type名称
"properties":{//参数
"id":{//Field属性
"type":"long",//类型
"store":true//是否存储
},
"title": {
"type":"long",
"store":true,
"index":"analyzed",//是否索引
"analyzer":"standard"//分词形式
},
"content": {
"type":"long",
"store":true,
"index":"analyzed",
"analyzer":"standard"
}
}
}
}
}
-
2.先创建索引库,后设置mapping
- 解析:
- 请求http://127.0.0.1:9200/index-lby/test03/_mapping
- http://127.0.0.1:9200:ES地址
- index-lby:索引库
- test03:索引库中的Type
- _mapping:mapping操作
- json串解析
- json在先创建索引库的请款下,并且已经在请求的路径上添加了Type,json中就不需要写mapping了
- json中的type需要和请求路径的type保持一致
- 请求http://127.0.0.1:9200/index-lby/test03/_mapping
-
3.删除索引库
在postman中使用delete加上资源路径例如http://127.0.0.1:9200/index-1,就可以将index-1索引库删除
-
4.创建文档document
解析
-
使用post请求
-
5.删除文档
-
解析
- 通过ID进行删除
- http://127.0.0.1:9200/index-lby/article3/2
- 删除id为2的article3的文档
-
6.修改文档
- 和添加基本一致
- http://127.0.0.1:9200/index-lby/article2/1
- 指定索引库,文档名,和文档对应的id,就可以修改当前的文档
-
7.查询文档-根据id查询
-
解析
-
8.查询文档-term查询
-
解析
-
{ "query":{ "term":{ "title":"查" } } }
- query:固定写法,代表查询
- term:代表查询的Field(字段)
- Body
- hits:命中的数据
- total:命中了几条数据
- 下面的[],里面是查询的结果
- 不支持中文分词
- 只能查询一个中文汉字
- 不支持中文分词
-
9.查询文档-querystring查询
-
解析
- http://127.0.0.1:9200/index-lby/article5/_search和querystring查询没有区别
- 查询语法
-
{ "query":{ "query_string":{ "default_field":"content", "query":"结果" } } }
- query:查询
- query_string:固定写法
- default_field:代表要查询的field
- query:查询条件
- 查询内容随意些,会先把查询的内容进行分词,然后再查询
【*】IK 分词器和ElasticSearch集成使用
-
解析
- http://127.0.0.1:9200/_analyze?analyzer=standard&text=我是LBY
- _analyze:代表分词
- analyzer=standard:使用标准分词
- 使用get查询就可以
【*】ElasticSearch集成IK分词器
- 将elasticsearch分词器压缩包解压到elasticsearch-5.6.8\plugins下,并重命名文件夹为analysis-ik,重启elasticsearch
-
K提供了两个分词算法ik_smart 和 ik_max_word
- 其中 ik_smart 为最少切分,ik_max_word为最细粒度划分
- 安装之后可以使用中文分析器进行查询
【*】 ElasticSearch集群
一个集群由 一个唯一的名字标识,这个名字默认就是“elasticsearch”
node:节点,集群中的一台服务器就是一个节点
1.ES分片逻辑模型
- 每个分片都有一个备份
2.ES集群物理模型
- 索引库的分片和备份分片不要放在同一台服务器上, 服务器挂掉备份也消失了,起不到高可用的作用
- 解决了高并发的问题,因为备份分片也是起作用的
3.ES集群搭建
- 准备三台elasticsearch服务器(也就是将ES的安装文件夹复制三分,但是注意要删除安装目录的data文件夹,因为里面存的是数据信息,如果以前使用过,里面会有索引库和Type等信息,配置集群需要使用全新的)
-
分别修改三台服务器es的config\elasticsearch.yml配置文件,在末尾添加如下信息
-
node1
#节点1的配置信息:
#集群名称,保证唯一
cluster.name: my-elasticsearch
#节点名称,必须不一样
node.name: node-1
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9201
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9301
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
- node2
#节点2的配置信息:
#集群名称,保证唯一
cluster.name: my-elasticsearch
#节点名称,必须不一样
node.name: node-2
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9202
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9302
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
- node3
#节点3的配置信息:
#集群名称,保证唯一
cluster.name: my-elasticsearch
#节点名称,必须不一样
node.name: node-3
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9203
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9303
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
- 搭建成功如图 所示
- 在集群上新建索引库 http://127.0.0.1:9201/es-cluster,连接集群的任何节点都可以
- 成功效果如图
- 添加映射
{
"lby":{
"properties":{
"id":{
"type":"long",
"store":true
},
"title":{
"type":"text",
"store":true,
"analyzer":"ik_smart"
},
"content":{
"type":"text",
"store":true,
"analyzer":"ik_smart"
}
}
}
}
- 解析
- 如果type的类型不是text,则不能设置analyzer的类型
- 添加mapping成功图示
- 向ES集群添加内容
http://127.0.0.1:9201/es-cluster/lby/2
{
"id":2,
"title":"湖北省委书记应勇:“过五关、斩六将、办七八个手续、十分辛苦”的事要坚决杜绝",
"content":"连日来,如何推动湖北人员安全有序流动一直备受关注。3月21日下午,湖北省在汉召开统筹推进全省疫情防控和经济社会发展工作座谈会,湖北省委书记应勇对此作了要求。"
}
- ES集群添加内容成功展示
【*】SpringBoot整合ES
- maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<!--设置maven的编译级别,默认是1.5的,有警告,这里我们设置为1.8消除警告-->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0-rc2</version>
</dependency>
<!-- springboot整合freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
</dependencies>
- 配置文件
spring:
data:
elasticsearch:
####集群名称
cluster-name: my-elasticsearch
####地址
cluster-nodes: 127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303
- 实体类
@Data//注解在类上, 为类提供读写属性, 此外还提供了 equals()、hashCode()、toString() 方法
@Document(indexName = "index_es", type = "cloud_disk")//说明该注解将被包含在javadoc中,indexName:索引库的名称,type:ES的type(相当于数据库的表)
public class CloudDiskEntity {
@Id
@Field(type = FieldType.Long, store = true)
private long id;
@Field(type = FieldType.text, store = true, analyzer = "ik_smart")
private String title;
@Field(type = FieldType.text, store = true, analyzer = "ik_smart")
private String content;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
- dao层
/*ElasticsearchRepository第二个泛型为索引id的类型,如果为String则指定String,如果为Long指定Long*/
public interface CloudDiskDao extends ElasticsearchRepository<CloudDiskEntity, Long> {
List<CloudDiskEntity> findByTitle(String title);
List<CloudDiskEntity> findByTitleOrContent(String title, String content);
List<CloudDiskEntity> findByTitleOrContent(String title, String content, Pageable pageable);
}
- 解析:
- 通过继承ElasticsearchRepository接口,可以使用ElasticsearchRepository接口提供的一些简单的方法
- ElasticsearchRepository的第一个参数是ES要操作对象的实体,第二个参数是实体主键的类型
- 当然可以使用一些自定义的方法,但是要注意规则
-
常用查询命名规则
关键字 | 命名规则 | 解释 | 示例 |
---|---|---|---|
and | findByField1AndField2 | 根据Field1和Field2获得数据 | findByTitleAndContent |
or | findByField1OrField2 | 根据Field1或Field2获得数据 | findByTitleOrContent |
is | findByField | 根据Field获得数据 | findByTitle |
not | findByFieldNot | 根据Field获得补集数据 | findByTitleNot |
between | findByFieldBetween | 获得指定范围的数据 | findByPriceBetween |
lessThanEqual | findByFieldLessThan | 获得小于等于指定值的数据 | findByPriceLessThan |
- 操作ES内容的controller
@RestController
public class CloudDiskController {
private CloudDiskDao cloudDiskDao;
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
public CloudDiskController(CloudDiskDao cloudDiskDao, ElasticsearchTemplate elasticsearchTemplate) {
this.cloudDiskDao = cloudDiskDao;
this.elasticsearchTemplate = elasticsearchTemplate;
}
/*创建索引*/
@GetMapping("/creatIndex")
public void creatIndex(){
elasticsearchTemplate.createIndex(CloudDiskEntity.class);
}
/*添加数据*/
@GetMapping("/creatInfo")
public void saveEsInfo(){
for (long i = 0; i < 10; i ++){
CloudDiskEntity cloudDiskEntity = new CloudDiskEntity();
cloudDiskEntity.setId(i);
cloudDiskEntity.setTitle("标题"+i);
cloudDiskEntity.setContent("内容"+i);
cloudDiskDao.save(cloudDiskEntity);
}
}
/*删除*/
@GetMapping("/deleteInfo/{id}")
public void deleteInfor(@PathVariable Long id){
cloudDiskDao.deleteById(id);
//cloudDiskDao.deleteAll();
}
/*修改添加一样,将对应当前id的删掉,再添加*/
@GetMapping("/updateInfo")
public void updateInfo(){
CloudDiskEntity cloudDiskEntity = new CloudDiskEntity();
cloudDiskEntity.setId(1);
cloudDiskEntity.setTitle("标题修改");
cloudDiskEntity.setContent("内容修改");
cloudDiskDao.save(cloudDiskEntity);
}
/*查询所有*/
@GetMapping("/findAll")
public void findAll() throws Exception {
Iterable<CloudDiskEntity> CloudDiskEntitys = cloudDiskDao.findAll();
CloudDiskEntitys.forEach(a-> System.out.println(a));
}
/*根据ID查询*/
@GetMapping("/testFindById")
public void testFindById() throws Exception {
Optional<CloudDiskEntity> optional = cloudDiskDao.findById(1l);
CloudDiskEntity CloudDiskEntity = optional.get();
System.out.println(CloudDiskEntity);
}
/*根据字段Title查询*/
@GetMapping("/testFindByTitle")
public void testFindByTitle() throws Exception {
List<CloudDiskEntity> list = cloudDiskDao.findByTitle("标题修改");
list.stream().forEach(a-> System.out.println(a));
}
/*根据字段Title查询和Content查询*/
@GetMapping("/testFindByTitleOrContent")
public void testFindByTitleOrContent() throws Exception {
Pageable pageable = PageRequest.of(0, 15);
cloudDiskDao.findByTitleOrContent("标题", "修改", pageable)
.forEach(a-> System.out.println(a));
}
/*根据query_string查询*/
@GetMapping("/testNativeSearchQuery")
public void testNativeSearchQuery() throws Exception {
//创建一个查询对象
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.queryStringQuery("修改").defaultField("title"))
.withPageable(PageRequest.of(0, 15))
.build();
//执行查询
List<CloudDiskEntity> CloudDiskEntityList = elasticsearchTemplate.queryForList(query, CloudDiskEntity.class);
CloudDiskEntityList.forEach(a-> System.out.println(a));
}
}
- SpringBoot的启动类
@SpringBootApplication
@EnableElasticsearchRepositories(basePackages = "com.lby.responsity")
public class LbyApplication {
public static void main(String[] args) {
SpringApplication.run(LbyApplication.class,args);
}
}