开源搜索引擎,从海量数据中快速找到需要的内容
elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域。而elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。
elasticsearch底层是基于lucene来实现的。
Lucene是一个Java语言的搜索引擎类库,提供了搜索引擎的核心API
Lucene优势:以扩展、高性能(基于倒排索引)
Lucene缺点:只限于Java语言开发、学习曲线陡峭、不支持水平扩展
倒排索引的概念是基于MySQL这样的正向索引。
根据id建立索引。id和title建表,如果基于title做模糊查询,那么只能根据id进行逐行扫描。
是根据文档找词条的过程。
优点:
有两个非常重要的概念:
创建倒排索引是对正向索引的一种特殊处理:
是根据词条找文档的过程。
优点:
文档
es是面向文档存储的,可以是数据库的一条商品数据、一个订单信息。文档数据会被序列化为json格式后存储在es中。
字段
json文档中往往包含很多的字段(field),类似于数据库中的列。
索引
相同类型的文档的集合,可以把索引当做数据库中的表。
映射
数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此索引库中的映射,就是索引中文档的字段约束信息,类似表的结构约束。
mysql
擅长事务类型操作,可以确保数据的安全和一致性
elasticsearch
擅长海量数据的搜索、分析、计算
MySQL | Elasticsearch | 说明 |
---|---|---|
Table | Index | 索引(index),就是文档的集合,类似数据库的表(table) |
Row | Document | 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式 |
Column | Field | 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column) |
Schema | Mapping | Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema) |
SQL | DSL | DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD |
作用
模式
如何扩展词条、停用词条
DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置comment>
<entry key="ext_dict">ext.dicentry>
<entry key="ext_stopwords">stopword.dicentry>
properties>
Rest(PUT、GET、DELETE)
mapping是对索引库中文档的约束,常见的mapping属性包括:
# PUT /索引库名称
PUT /heima
{
"mappings": {
"properties": {
"info":{
"type": "text",
"analyzer": "ik_smart"
},
"email":{
"type": "keyword",
"index": "falsae"
},
"name":{
"properties": {
"firstName": {
"type": "keyword"
}
}
},
// ... 略
}
}
}
索引库一旦创建,无法修改mapping中已有的字段,但是允许添加新字段到mapping中。
PUT /索引库名/_mapping
{
"properties": {
"新字段名":{
"type": "integer"
}
}
}
GET /索引库名
DELETE /索引库名
可以用post和put,但是post新增不指定id系统会自动新建一个id;而get不指定id系统不会分配。
POST /索引库名/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
"字段3": {
"子属性1": "值3",
"子属性2": "值4"
},
// ...
}
GET /{索引库名称}/_doc/{id}
DELETE /{索引库名}/_doc/id值
POST /索引库名/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
"字段3": {
"子属性1": "值3",
"子属性2": "值4"
},
// ...
}
POST /{索引库名}/_update/文档id
{
"doc": {
"字段名": "新的值",
}
}
ES中支持两种地理坐标数据类型:
copy_to:将当前字段拷贝到指定字段
核心是client.indices()方法来获取索引库的操作对象。
在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接:
1、导入es的RestHighLevelClient依赖:
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
dependency>
2、因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:
<properties>
<java.version>1.8java.version>
<elasticsearch.version>7.12.1elasticsearch.version>
properties>
3、初始化RestHighLevelClient
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
//填写自己的IP值和端口
HttpHost.create("http://192.168.150.101:9200")
));
//MAPPING_TEMPLATE是自己定义的格式
@Test
void createHotelIndex() throws IOException {
// 1.创建Request对象
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2.准备请求的参数:DSL语句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3.发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
@Test
void testDeleteHotelIndex() throws IOException {
// 1.创建Request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
@Test
void testExistsHotelIndex() throws IOException {
// 1.创建Request对象
GetIndexRequest request = new GetIndexRequest("hotel");
// 2.发送请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 3.输出
System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}
数据库结构和索引库结构会不一致,所以需要新建类库来使结构保持一致。
@Test
void testAddDocument() throws IOException {
// 1.根据id查询酒店数据
Hotel hotel = hotelService.getById(61083L);
// 2.转换为文档类型
HotelDoc hotelDoc = new HotelDoc(hotel);
// 3.将HotelDoc转json
String json = JSON.toJSONString(hotelDoc);
// 1.准备Request对象
IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
// 2.准备Json文档
request.source(json, XContentType.JSON);
// 3.发送请求
client.index(request, RequestOptions.DEFAULT);
}
@Test
void testGetDocumentById() throws IOException {
// 1.准备Request
GetRequest request = new GetRequest("hotel", "61082");
// 2.发送请求,得到响应
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3.解析响应结果
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
@Test
void testDeleteDocument() throws IOException {
// 1.准备Request
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
@Test
void testUpdateDocument() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("hotel", "61083");
// 2.准备请求参数
request.doc(
"price", "952",
"starName", "四钻"
);
// 3.发送请求
client.update(request, RequestOptions.DEFAULT);
}
BulkRequest做批量操作,有批量的增、删、查操作。
@Test
void testBulkRequest() throws IOException {
// 批量查询酒店数据
List<Hotel> hotels = hotelService.list();
// 1.创建Request
BulkRequest request = new BulkRequest();
// 2.准备参数,添加多个新增的Request
for (Hotel hotel : hotels) {
// 2.1.转换为文档类型HotelDoc
HotelDoc hotelDoc = new HotelDoc(hotel);
// 2.2.创建新增文档的Request对象
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc), XContentType.JSON));
}
// 3.发送请求
client.bulk(request, RequestOptions.DEFAULT);
}