概述
-
结合(kibana:数据可视化)(Logstash和Beats:数据抓取),应用于日志数据分析,实时监控。
- elastic stack(ELK):是以elasticsearch为核心的技术栈,包括kibana,Logstash和Beats
- Lucene:Apache的开源搜索引擎类库,提供搜索引擎的核心API
倒排索引
- 文档(document):每条数据就是一个文档,JSON格式
- 词条(term):文档按照语义分成的词语
- 索引:相同类型的文档的集合,类似于表
- 映射:索引中文档的字段约束,类似于表的结构约束
- DSL:elasticsearch提供的JSON风格的请求语句,实现CRUD
id | title | price |
1 | 小米手机 | 3.5k |
2 | 华为手机 | 5k |
3 | 小米手环 | 0.3k |
词条 | 文档 |
小米 | 1,3 |
手机 | 1.2 |
华为 | 2 |
手环 | 3 |
执行步骤:搜索小米手机 > 分词:(‘小米’,‘手机’)两个词条 > 去词条列表查询文档 id :(小米:1,3)(手机:1,2) > 根据文档id查询文档得到id为:1,2,3的文档 > 存入结果集
Mysql和Elasticsearch的区别
- Mysql:擅长事务类型操作,可以确保数据安全和一致
- Elasticsearch:擅长海量数据的搜索、分析、计算
安装ES
注意:当docker异常关闭的时候,会出现:Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
需要重启docker服务:systemctl start docker.service
具体安装见:elasticsearch.md文档
分词器:采用IK分词,默认的ES分词器对中文不友好
拓展词库:在IK文件中config目录下的IkAnalyzer.cfg.xml文件
- 增加词汇文件名:ext.dic(需要创建在config目录下)
- 禁用词汇文件名:stopword.dic
索引库操作
mapping:是对索引库中文档的约束,常见的mapping属性包括
- type:字段数据类型
- 字符串:text(可分词的文本)、keyword(精确值,例如:品牌,国家,ip等)不需要分词
- 数值:java的数据类型
- 布尔:boolean
- 日期:date
- 对象:object
- index:是否创建索引,默认为true
- analyzer:使用哪种分词器
- properties:该字段的子字段
- 创建索引库:PUT /索引库名
- 查询索引库:GET /索引库名
- 删除索引库:DELETE /索引库名
- 添加字段:PUT /索引库名/_mapping
文档操作
- 新增文档:POST /索引库名/_doc/文档id
- 删除文档:DELETE /索引库名/_doc/文档id
- 查询文档:GET /索引库名/_doc/文档id
修改文档
1:全量修改,会删除旧文档,添加新文档
PUT /索引库名/_doc/文档id
{
"字段1":"值1",
"字段2":"值2"
}
2:增量修改,修改指定字段值
POST /索引库名/_update/文档id
{
"doc":{
"字段名":"新的值"
}
}
RestClient操作索引库
-
初始化索引库
// 初始化索引库对象
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://ip地址:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
-
创建索引库
// 创建索引库(MAPPING_TEMPLATE为DSL语句)
// MAPPING_TEMPLATE:定义为静态常量
void testCreateIndex() throws IOException {
// 1、创建request对象
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2、创建索引库的DSL语句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3、发送请求
client.indices().create(request, RequestOptions.DEFAULT);
System.out.println("索引库创建完成");
}
-
删除索引库
// 删除索引库
void testDeleteIndex() throws IOException {
// 1、创建request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2、发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
-
判断索引库是否存在
// 判断索引库是否存在
void testExistsIndex() throws IOException {
// 1、创建request对象
GetIndexRequest request = new GetIndexRequest("hotel");
// 2、发送请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 输出结果
System.out.println(exists ? "索引库已存在" : "索引库不存在");
}
RestClient操作文档
到数据库查询数据,导入到索引库中,实现数据的CRUD
-
新增文档
// 新增文档
void testAddDocument() throws IOException {
// 根据id查询数据(根据Mybatis-Plus)
Hotel hotel = hotelService.getById(61083L);
// 封装为Doc类型(保持数据一致性):location封装了精度和维度两个数据
HotelDoc hotelDoc = new HotelDoc(hotel);
// 创建request对象
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
// 准备json文档,将从数据库查询到的数据封装成Doc,转换成JSON格式
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
// 发送请求,创建文档
client.index(request, RequestOptions.DEFAULT);
}
-
查询文档
// 查询文档
void testGetDocument() throws IOException {
// 1、创建Request
GetRequest request = new GetRequest("hotel","61083");
// 2、发送请求,得到响应
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3、解析响应结果,反序列化为java封装对象
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
-
更新文档
// 局部修改文档
void testUpdateDocument() throws IOException {
// 1、创建Request对象
UpdateRequest request = new UpdateRequest("hotel","61083");
// 2、准备请求参数,修改内容
request.doc(
"price","1000",
"city","广州"
);
// 3、发送请求
client.update(request, RequestOptions.DEFAULT);
}
-
删除文档
// 删除文档 void testDeleteDocument() throws IOException { // 1、创建Request对象 DeleteRequest request = new DeleteRequest("hotel","61083"); // 2、发送请求 client.delete(request, RequestOptions.DEFAULT); }
-
批量导入文档
// 批量新增文档
void testBulkDocument() throws IOException {
// 使用MybatisPlus查询所有数据
List<Hotel> hotelList = hotelService.list();
// 1、创建Request对象
BulkRequest request = new BulkRequest();
// 2、用for循环,将hotel转换为HotelDoc类型
for (Hotel hotel : hotelList) {
HotelDoc hotelDoc = new HotelDoc(hotel);
// 创建新增文档的Request对象
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc),XContentType.JSON));
}
// 3、发送请求
client.bulk(request, RequestOptions.DEFAULT);
}