ElasticSearch 基础
1.ES简介
S是使用java 语言并且基于lucence编写的搜索引擎框架,他提供了分布式的全文搜索功能,提供了一个统一的基于restful风格的web 接口。
lucence:一个搜索引擎底层
分布式:突出ES的横向扩展能力
全文检索:将一段词语进行分词,并将分出的词语统一的放在一个分词库中,再搜索时,根据关键字取分词库中检索,找到匹配的内容(倒排索引)。
restful风格的web 接口:只要发送一个http请求,并且根据请求方式的不同,携带参数的不同,执行相应的功能。
应用广泛:WIKI, github,Gold man
2. ES 和 solr
1.solr 查询死数据,速度比es快。但是数据如果是改变的,solr查询速度会降低很多,ES的查询速度没有明显的改变
2.solr搭建集群 依赖ZK,ES本身就支持集群搭建
3.最开始solr 的社区很火爆,针对国内文档 少,ES出现后,国内社区火爆程度 上升,,ES的文档非常健全
4.ES对云计算和大数据支持很好
3. 倒排索引
1.将存放的数据以一定的方式进行分词,并将分词的内容存放到一个单独的分词库中。
2.当用户取查询数据时,会将用户的查询关键字进行分词,然后去分词库中匹配内容,最终得到数据的id标识
3.根据id标识去存放数据的位置拉去指定数据
4. ES的基本操作
4.1 索引 index,分片,备份
# 1 ES的服务中可以创建多个索引,
# 2 每个索引默认分成5片存储,
# 3 每一个至少有一个备份分片
# 4 备份分片正常不会帮助检索数据,除非ES的检索压力很大的情况发送
# 5 如果只有一台ES,是不会有备份分片的,只有搭建集群才会产生
4.2 类型 type
# 1 ES5.x下,一个index可以创建多个type
# 2 ES6.x下,一个index只能创建一个type
# 3 ES7.x下,直接舍弃了type,没有这玩意了
4.3 文档 document
# 一个type下可以有多个文档doc,这个doc就类似mysql表中的行
4.4 属性 field
一个文档中可以包含多个属性,类似于mysql 表中的一行数据有多个列
4.5 操作ES 的Restful语法
GET请求: http://ip:port/index :查询索引信息 http://ip:port/index/type/doc_id :查询指定的文档信息 POST请求: http://ip:port/index/type/_search: 查询文档,可以在请求体中添加json字符串来代表查询条件 http://ip:port/index/type/doc_id/_update: 修改文档,在请求体中添加json字符串来代表修改的信息 PUT请求: http://ip:port/index : 创建一个索引,需要在请求体中指定索引的信息 http://ip:port/index/type/_mappings:代表创建索引时,指定索引文档存储属性的信息 DELETE 请求: http://ip:port/index: 删除跑路 http://ip:port/index/type/doc_id: 删除指定的文档
4.6 创建一个索引
#创建一个索引
#number_of_shards 分片
#number_of_replicas 备份
PUT /person
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
}
}
4.7 查看一个索引
// 2 查看索引,可以通过图形界面,也可以通过发请求来查看,信息如下:
GET /parson
4.8 ES中Field可以指定的类型
字符串类型:
text: 一般用于全文检索,将当前field 进行分词
keyword:当前field 不会进行分词
数值类型:
long:
Intger:
short:
byte:
double:
float:
half_float: 精度比float 小一半
scaled_float:根据一个long 和scaled 来表达一个浮点型 long-345, -scaled 100 ->3.45
时间类型:
date类型,根据时间类型指定具体的格式
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
布尔类型:
boolean 类型,表达true 和false
二进制类型:
binary类型暂时支持Base64编码的字符串
范围类型:
integer_range:
float_range:
long_range:赋值时,无需指定具体的内容,只需存储一个范围即可,gte,lte,gt,lt,
double_range:
date_range:
ip_range:
PUT range_index
{
"settings": {
"number_of_shards": 2
},
"mappings": {
"_doc": {
"properties": {
"expected_attendees": {
"type": "integer_range"
},
"time_frame": {
"type": "date_range",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
PUT range_index/_doc/1?refresh
{
"expected_attendees" : {
"gte" : 10,
"lte" : 20
},
"time_frame" : {
"gte" : "2015-10-31 12:00:00",
"lte" : "2015-11-01"
}
}
经纬度类型:
geo_point:用来存储经纬度
IP类型:
ip:可以存储IPV4 和IPV6
其他的数据类型,参考官网
4.9 创建索引并指定数据结构
#创建索引,指定数据类型
PUT /book
{
"settings": {
#分片数
"number_of_shards": 5,
#备份数
"number_of_replicas": 1
},
#指定数据类型
"mappings": {
#类型 Type
"novel":{
#文档存储的field
"properties":{
#field属性名
"name":{
#类型
"type":"text",
#指定分词器
"analyzer":"ik_max_word",
#指定当前的field可以被作为查询的条件
"index":true,
#是否需要额外存储
"store":false
},
"author":{
"type":"keyword"
},
"count":{
"type":"long"
},
"on-sale":{
"type":"date",
#指定时间类型的格式化方式
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"descr":{
"type":"text",
"analyzer":"ik_max_word"
}
}
}
}
}
4.10 文档操作
文档在ES服务中的唯一标识, _indx ,_type,_id 三个内容为组合,锁定一个文档,操作时添加还时修改操作,
4.11 新建文档
自动生成id
#添加文档,自动生成id
POST /book/novel
{
"name":"盘龙",
"author":"我吃西红柿",
"count":100000,
"on-sale":"2001-01-01",
"descr":"大小的血睛鬃毛狮,力大无穷的紫睛金毛猿,毁天灭地的九头蛇皇,携带着毁灭雷电的恐怖雷龙……这里无奇不有,这是一个广博的魔幻世界。强者可以站在黑色巨龙的头顶遨游天际,恐怖的魔法可以焚烧江河,可以毁灭城池,可以夷平山岳……"
}
#添加文档,手动指定id
PUT /book/novel/1
{
"name":"红楼梦",
"author":"曹雪芹",
"count":10000000,
"on-sale":"2501-01-01",
"descr":"中国古代章回体长篇小说,中国古典四大名著之一,一般认为是清代作家曹雪芹所著。小说以贾、史、王、薛四大家族的兴衰为背景,以富贵公子贾宝玉为视角,以贾宝玉与林黛玉、薛宝钗的爱情婚姻悲剧为主线,描绘了一批举止见识出于须眉之上的闺阁佳人的人生百态,展现了真正的人性美和悲剧美"
}
4.12 修改文档
1.覆盖式修改
#添加文档,手动指定id PUT /book/novel/1 { "name":"红楼梦", "author":"曹雪芹", "count":1000444, "on-sale":"2501-01-01", "descr":"中国古代章回体长篇小说,中国古典四大名著之一,一般认为是清代作家曹雪芹所著。小说以贾、史、王、薛四大家族的兴衰为背景,以富贵公子贾宝玉为视角,以贾宝玉与林黛玉、薛宝钗的爱情婚姻悲剧为主线,描绘了一批举止见识出于须眉之上的闺阁佳人的人生百态,展现了真正的人性美和悲剧美" }
2.使用doc修改方式
#修改文档,使用doc 方式
POST /book/novel/1/_update
{
"doc":{
#指定需要修改的field和对应的值
"count":566666
}
}
4.13 删除文档
#根据id删除文档
DELETE /book/novel/3mEnk3MBaSKoGN4T2olw
5.java 操作ElasticSearch
创建maven工程
导入依赖
<!-- 1.elasticsearch-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.10</version>
</dependency>
<!-- 2.elasticsearch 高级API-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.10</version>
</dependency>
<!-- 3.junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- 4.lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
5.1创建client连接
public static RestHighLevelClient getClient(){
HttpHost httpHost = new HttpHost("localhost", 9200, "http");
RestClientBuilder builder = RestClient.builder(httpHost);
//创建RestHighLevelClient
RestHighLevelClient client=new RestHighLevelClient(builder);
return client;
}
5.2 创建索引
package com.test;
import com.utils.EsClient;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.junit.Test;
public class Demo2 {
RestHighLevelClient client = EsClient.getClient();
String index = "person";
String type="man";
@Test
public void createIndx() throws Exception{
// 1.准备关于索引的setting
Settings.Builder settings = Settings.builder()
.put("number_of_shards", 2)
.put("number_of_replicas", 1);
// 2.准备关于索引的mapping
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(type,mappings);
// 4.使用client 去连接ES
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println("response:"+response.toString());
}
}
5.3 检查索引是否存在
@Test
public void existTest() throws IOException {
// 1.准备request 对象
GetIndexRequest request = new GetIndexRequest(index);
// 2.通过client 去 操作
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 3输出结果
System.out.println(exists);
}
5.4 删除索引
public void testDelete() throws IOException {
// 1.获取request
DeleteIndexRequest request = new DeleteIndexRequest(index);
// 2.使用client 操作request
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
// 3.输出结果
System.out.println(delete.isAcknowledged());
}
5.5 java 操作文档
5.5.1 添加文档操作
@Test
public void createDocTest() throws IOException {
// 1.准备一个json数据
Person person = new Person(1,"张三",33,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 操作request对象生成doc
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
// 4.输出返回结果
System.out.println(response.getResult().toString());
}
5.5.2 修改文档
@Test public void updateDocTest() throws Exception{ // 1.创建要跟新的Map Map<String,Object> doc = new HashMap<>(); doc.put("name","张三三"); // 2.创建request, 将doc 封装进去 UpdateRequest request = new UpdateRequest(index,type,"1"); request.doc(doc); // 3. client 去操作 request UpdateResponse response = client.update(request, RequestOptions.DEFAULT); // 4.输出 更新结果 System.out.println(response.getResult()); }
5.5.3 删除文档
public void deleteDocTest() throws Exception{
// 1.封装删除对象
DeleteRequest request = new DeleteRequest(index,type,"1");
// 2 client 操作 request对象
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
// 3.输出结果
System.out.println(response.getResult().toString());
}
5.5.4 java批量操作文档
public void bulkCreateDoc() throws Exception{
// 1.准备多个json 对象
Person p1 = new Person(1,"张三",23,new Date());
Person p2 = new Person(2,"里斯",24,new Date());
Person p3 = new Person(3,"王武",24,new Date());
String json1 = mapper.writeValueAsString(p1);
String json2 = mapper.writeValueAsString(p2);
String json3 = mapper.writeValueAsString(p3);
// 2.创建request
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest(index,type,p1.getId().toString()).source(json1,XContentType.JSON))
.add(new IndexRequest(index,type,p2.getId().toString()).source(json2,XContentType.JSON))
.add(new IndexRequest(index,type,p3.getId().toString()).source(json3,XContentType.JSON));
// 3.client 执行
BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
// 4.输出结果
System.out.println(responses.getItems().toString());
}
5.5.5 批量删除
public void bulkDelete() throws Exception{
// 1.创建Request 对象
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new DeleteRequest(index,type,"1"));
bulkRequest.add(new DeleteRequest(index,type,"2"));
bulkRequest.add(new DeleteRequest(index,type,"3"));
// 2.执行
BulkResponse re = client.bulk(bulkRequest, RequestOptions.DEFAULT);
// 3.输出结果
System.out.println(re.toString());
}