一、ES 相关介绍
1.ES是一个使用Java语言并且基于Lucene编写的搜索引擎框架,提供了分布式的全文搜索功能,还提供了一个统一的基于RESTful风格的Web接口,官方客户端也对多种语言提供了相应的API。
2.Lucene:它本身就是一个搜索引擎的底层。属于Apache的一个顶级项目,和Solr一样属于核心搜索库
3.分布式:ES主要是为了突出自身的(横向)高扩展能力
4.全文检索:将一段词语进行分词,并且将分出的单个词语统一的放到一个分词库中;在搜索时,根据关键字去分词库中检索,找到匹配的内容。(倒排索引)
5.RESTful风格的Web接口:操作ES很简单,只需要发送一个http请求,并且根据请求方式不同和携带参数的而不同,执行相应的功能。
6.应用广泛:Github.com, Wiki,Goldman用ES维护日均近10TB的数据。
二、ElasticSearch和Solr之间的区别
(1).查询效率:Solr查询死数据(即数据不可改变,不可多或少)时,检索速度优先于ES;若数据实时改变时,Solr的查询效率将大幅降低,而ES检索效率几乎不变
(2).搭建集群:Solr搭建基于Zookeeper来帮助管理,ES本身支持集群的搭建,不需要第三方介入
(3).文档社区:Solr的社区开始十分火爆,但针对国内的文档并不多;在ES出现之后,ES的相关社区火爆程度直线上升,ES文档也相对更健全
(4).云计算和大数据:ES针对现在的主流技术(云计算和大数据)的支持和处理相对特别友好。
概念说明:
倒排索引:大致将ES服务分为两块(分词库和数据区),将存放的数据以一定的方式进行分词,并且将分词的内容存放到一个单独的分词库中
<1>.当用户查询数据时,会先将用户的查询关键词进行分词
<2>.然后去分词库中匹配内容,最终得到数据的索引标识
<3>.根据索引标识去存放数据区拉取指定的数据
三、ES的安装指引
1.安装ES & Kibana (ES 的可视化界面)
说明:具体下载安装指南此文参考文献:https://www.jianshu.com/p/05e203ea51af
(1).拉取ES镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.5.0
(2).单节点运行ES
docker run -d --restart=always -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.5.0
(3.1).多节点运行ES
创建一个docker-compose.yml 文件
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data02:/usr/share/elasticsearch/data
networks:
- elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data03:/usr/share/elasticsearch/data
networks:
- elastic
volumes:
data01:
driver: local
data02:
driver: local
data03:
driver: local
networks:
elastic:
driver: bridge
- 节点 es01 监听 localhost:9200, es02 和 es03 类似
- 数据卷 data01,data02,data03。可以持久化
- 启动:docker-compose up
- 停止:docker-compose down
- 停止并删除数据卷:docker-compose down -v
- 查看节点是否启动
curl -X GET "localhost:9200/_cat/nodes?v&pretty"
(3.2)设置vm.max_map_count
grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=262144
sysctl -w vm.max_map_count=262144
(4)安装Kibana
docker pull docker.elastic.co/kibana/kibana:7.5.0
(5)设置kibana
docker run --link YOUR_ELASTICSEARCH_CONTAINER_NAME_OR_ID:elasticsearch -p 5601:5601 {docker-repo}:{version}
docker run -d --restart=always --link a72adb9bf49a:elasticsearch -p 5601:5601 docker.elastic.co/kibana/kibana:7.5.0
(6).拉取logstash镜像
docker pull docker.elastic.co/logstash/logstash:7.5.0
(7).安装elasticsearch插件监控管理
docker pull mobz/elasticsearch-head:5
docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5
(8).安装ik分词器
从github项目中查找ik分词器:
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
<1>.先通过docker进入到es容器内部:docker exec -it 容器id bash
<2>.容器内部切换目录并执行安装:cd bin/
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
<3>.说明:国内网站下载比较慢,下载安装的kibana和ik分词器的版本都要和elasticsearch保持一致。
(9).重启ES通过执行docker命令重启es: docker restart
容器id
具体实现效果如下所示:
四、ES的数据结构
1.ES服务和MySQL数据库之间的比较:
ES服务:会搭建集群,可以创建多个索引,每个索引可以被分成5片存储,且每个分片都会存在至少一个备份分片;
备份分片默认不会帮助检索数据,只有当ES检索压力特别大的情况下,备份分片才会帮助检索数据;
备份分片必须存放在不同的服务器中;
对索引进行分片,可以提高检索数据的效率,存储数据容量得到提升。
ES 5.x版本中,一个索引index可以创建多个type;
ES 6.x版本中,一个索引index可以创建一个type;
ES 7.x版本中,一个索引index没有type。
ES 服务的index类似于MySQL的数据库;
ES 服务的type类似于MySQL的table;
ES 服务的document类似于MySQL的一行数据存在多个列。
2.常见数据类型
字符串类型 :
text:一般被用于全文检索,将当前Field进行分词
keyword:意旨关键字,当前Field不会被分词
数值类型:
long
integer
short
byte
double
float
half_float:表示精度比float小一半
scaled_float:根据一个long和scaled来表达一个浮点型 (例如:long-345 scaled-100 即表示3.45)
时间类型:date (针对时间类型指定具体的格式)
布尔类型:boolean
二进制类型:binary (暂时支持64位编码字符集)
范围类型:long_range (赋值时,无序指定具体内容,只需要存储一个范围即可)
经纬度类型:geo_point (用来存储经纬度)
ip类型:可以存储ipv4或ipv6
如果对其他数据类型感兴趣,可以参考如下官网进行学习
具体参考文献:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/mapping.html#field-datatypes
五、操作ES的RESTful语法
1.GET请求
(1).查询索引信息:http://ip:port/index
(2).查询指定文档信息:http://ip/port/index/type/doc_id
2.POST请求
(1).查询指定文档 (可在请求体中添加json字符串代替查询条件):http://ip:port/index/type/_search
(2).查询指定文档 (可在请求体中指定json字符串代替修改条件):http://ip/port/index/type/doc_id/_update
3.PUT请求
(1).创建索引 (需要在请求体中指定索引信息):http://ip:port/index
(2).创建索引时,指定索引文档存储的属性信息:http://ip/port/index/type/_mappings
4.DELETE请求
(1).删除索引 (需要在请求体中指定索引信息):http://ip:port/index
(2).删除指定文档信息:http://ip/port/index/type/doc_id
五、Java连接ES
1.创建Maven工程
2.导入依赖:
(1).elasticsearch
(2).elasticsearch 高级API
(3).junit
(4).lombok
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
</dependencies>
3.创建测试类,连接es
public class ESClient {
public static RestHighLevelClient getClient(){
//创建HttpHost对象
HttpHost host = new HttpHost("192.168.99.100",9200);
//创建 RestClientBuilder
RestClientBuilder builder = RestClient.builder(host);
//创建 RestHighLevelClient
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
六、Java操作ES索引
/**
* @ClassName Demo2
* @Description Java创建ES索引方式
* @Author AlexChen
* @Date 2020/8/23 17:17
* @Version 5.20
* @WebSite www.codeboy.top
**/
public class Demo2 {
RestHighLevelClient client = ESClient.getClient();
String index = "person";
String type = "man";
@Test
public void createIndex() throws IOException {
//1.准备关于索引的settings
Settings.Builder settings = Settings.builder()
.put("number_of_shards",3)
.put("number_of_replicas",1);
//2.准备关于索引的结构
XContentBuilder mappings = JsonXContent.contentBuilder()
.startObject()
.startObject("properties")
.startObject("name")
.field("type","text")
.endObject()
.startObject("age")
.field("type","integer")
.endObject()
.startObject("birthday")
.field("type","date")
.field("format","yyyy-MM-dd")
.endObject()
.endObject()
.endObject();
//3.将settings 和 mappings 封装到一个Request对象
CreateIndexRequest request = new CreateIndexRequest(index)
.settings(settings)
.mapping(mappings);
//4.通过client对象去连接ES并执行创建索引
CreateIndexResponse resp = client.indices().create(request, RequestOptions.DEFAULT);
//输入resp
System.out.println("resp>>>"+resp.toString());
}
}
public class Demo3 {
String index = "person";
RestHighLevelClient client = ESClient.getClient();
/**
* 判断ES指定索引是否存在
*/
@Test
public void exists() throws IOException {
//1.准备request 对象
GetIndexRequest request = new GetIndexRequest();
request.indices(index);
//2.通过client操作
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
//3.输出结果
System.out.println("返回值:"+exists);
}
/**
* 删除ES指定索引
*/
@Test
public void delete() throws IOException {
//1.准备request 对象
DeleteIndexRequest request = new DeleteIndexRequest();
request.indices(index);
//2.通过client操作
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
//3.输出结果
System.out.println("返回值:"+response.isAcknowledged());
}
}
七、Java操作文档
/**
* @ClassName TestDoc
* @Description Java操作文档
* @Author AlexChen
* @Date 2020/8/23 18:30
* @Version 5.20
* @WebSite www.codeboy.top
**/
public class TestDoc {
String index = "person";
String type = "man";
ObjectMapper mapper = new ObjectMapper();
RestHighLevelClient client = ESClient.getClient();
/**
* 创建一个文档
*/
@Test
public void createPerson() throws IOException {
//1.创建一个Json数据
Person person = new Person(1,"张三",23,new Date());
String json = mapper.writeValueAsString(person);
//2.准备一个request对象
IndexRequest request = new IndexRequest(index,type,person.getId().toString());
request.source(json, XContentType.JSON);
//3.通过client对象执行添加操作
IndexResponse resp = client.index(request, RequestOptions.DEFAULT);
//4.输出返回结果
System.out.println(resp.getResult().toString());
}
/**
* 更新一个文档
*/
@Test
public void updateDoc() throws IOException {
//1.创建一个Map对象,指定需要修改的内容
Map<String, Object> doc = new HashMap<String, Object>();
doc.put("name","埃里克森");
String docId = "1";
//2.创建request对象,封装数据
UpdateRequest request = new UpdateRequest(index,type,docId);
request.doc(doc);
//3.通过client对象执行
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
//4.输出返回结果
System.out.println(update.getGetResult().toString());
}
/**
* 删除一个文档
*/
@Test
public void deleteDoc() throws IOException {
//1.封装request对象,封装数据
DeleteRequest request = new DeleteRequest(index,type,"1");
//2.通过client对象执行
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
//3.输出返回结果
System.out.println(response.getResult().toString());
}
/**
* 批量添加文档
*/
@Test
public void batchCreateDoc() throws IOException {
//1.准备多个json数据
Person p1 = new Person(1,"张三",23,new Date());
Person p2 = new Person(2,"李四",24,new Date());
Person p3 = new Person(3,"王五",25,new Date());
String json1 = mapper.writeValueAsString(p1);
String json2 = mapper.writeValueAsString(p2);
String json3 = mapper.writeValueAsString(p3);
//2.创建request对象,将准备好的数据封装进去
BulkRequest request = new BulkRequest();
request.add(new IndexRequest(index,type,p1.getId().toString()).source(json1,XContentType.JSON));
request.add(new IndexRequest(index,type,p2.getId().toString()).source(json2,XContentType.JSON));
request.add(new IndexRequest(index,type,p3.getId().toString()).source(json3,XContentType.JSON));
//3.通过client执行
BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
//4.输出返回结果
System.out.println(bulk.toString());
}
/**
* 批量删除文档
*/
@Test
public void batchDeleteDoc() throws IOException {
//1.封装request对象
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest(index,type,"1"));
request.add(new DeleteRequest(index,type,"2"));
request.add(new DeleteRequest(index,type,"3"));
//2.通过client执行
BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
//3.输出返回结果
System.out.println(response);
}
}