一.ElasticSearch 简介
1.概述:
Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够实现在海量数据中快速检索到满足条件的数据,同时还可以实现分页、高亮显示等功能。
2.ELK技术栈:
-
Elasticsearch:存储、搜索、分析数据
-
Kibana:数据可视化、提供了图形化界面,可以操作ES
-
Logstash、Beats:数据抓取
3.倒排索引
3.1 概述
从文件的内容查找,得到包含这些内容的文件列表,再得到文件对应的信息,如文件名、作者、文件大小、创建时间等
3.2 实现过程
- 将文档的内容通过算法进行分词,得到一个词条列表
- 将词条列表当作key,包含该词条的文档id列表作为值,形成一张表
- 词条是唯一的,所以给词条创建索引,提高搜索效率
- 通过词条查询,得到文档ID,再通过文档ID查询到具体的文档
二.基础概念
1. index 索引(索引库)
- 索引就相当于MySql里的数据库,它是具有某种相似特性的文档集合。反过来说不同特性的文档一般都放在不同的索引里;
- 索引的名称必须全部是小写;
- 在单个集群中,可以定义任意多个索引;
- 索引具有mapping和setting的概念,mapping用来定义文档字段的类型,setting用来定义不同数据的分布。
2.文档(Document)
- 我们知道Java是面向对象的,而Elasticsearch是面向文档的,也就是说文档是所有可搜索数据的最小单元。ES的文档就像MySql中的一条记录,只是ES的文档会被序列化成json格式,保存在Elasticsearch中;
- 这个json对象是由字段组成,字段就相当于Mysql的列,每个字段都有自己的类型(字符串、数值、布尔、二进制、日期范围类型);
- 当我们创建文档时,如果不指定字段的类型,Elasticsearch会帮我们自动匹配类型;
- 每个文档都有一个ID,类似MySql的主键,咱们可以自己指定,也可以让Elasticsearch自动生成;
- 文档的json格式支持数组/嵌套,在一个索引(数据库)或类型(表)里面,你可以存储任意多的文档。
3.Field 字段
好比关系型数据库中列的概念,一个document有一个或者多个field组成。
三.索引库操作
前面我们已经介绍过了ES 是RESTful 风格的系统,所以我们需要先掌握RESTful 的四个关键词:PUT(修改),POST(添加),DELETE(删除),GET(查询)。其中在ES里面PUT和POST的界限并不是很分明,有时候PUT也作为添加。
1.创建索引库
创建空索引库
PUT /demo
{
"settings": {
"number_of_shards": "2",
"number_of_replicas": "0"
}
}
创建索引库并指定mapping
PUT /demo
{
"mappings": {
"properties": {
"info":{
# type: 指定类型
"type": "text",
# analyzer: 指定分词器
"analyzer": "ik_smart",
# index: 是否是索引
"index": true,
# store :是否存储
"store": true
},
"name":{
"properties": {
"firstName":{
"type":"keyword"
},
"lastName":{
"type":"keyword"
}
}
}
}
}
2.查询、删除索引库
#查询索引: GET /索引库名
GET /demo
#查询索引: DELETE /索引库名
DELETE /demo
3.修改索引库
#修改数据库,其实就是往索引库汇中添加字段
#PUT /索引库名/_mapping
PUT /demo/_mapping
{
"properties":{
"新字段名":{
"type":"integer"
}
}
}
四.文档操作
1.增加文档
POST /索引名/_doc/文档ID
{
//json格式数据
}
2.删除文档
#删除文档
DELETE /索引库名称/_doc/文档ID
3.修改文档
#PUT修改是直接覆盖,字段理应写全
PUT /索引名/_doc/文档ID
{
//json格式
}
#POST修改是不会覆盖的,用于修改部分字段
POST /索引库名/_update/文档id
{
"doc": {
"字段名": "新的值",
}
}
4.查询文档
4.1 查询文档
#根据文档ID查询文档
GET /索引库名称/_doc/文档ID
#查询全部文档
GET /索引库名称/_search
4.2 ES搜索
4.2.1 基本语法
#根据内容查询文档基本语法 (即搜索功能)
GET /索引库名称/_search
{
"query": {
"查询类型": {
"查询条件": "条件值"
}
}
}
4.2.2 全文检索查询
# match查询,单字段查询
GET /索引库名称/_search
{
"query": {
"match": {
"查询条件": "条件值"
}
},
"from": 0,
"size": 200
}
#multi_match 多字段查询,任意一个字段符合条件就算符合查询条件
GET /索引库名称/_search
{
"query": {
"multi_match": {
"query": "查询文本",
"fields": [字段1,字段2,字段3]
}
}
}
4.2.3 精确查询
# term查询 根据词条精确值查询
GET /索引库名称/_search
{
"query": {
"term": {
"字段": {
"value": "文本"
}
}
}
}
# range 查询 根据值的范围查询,一般应用在对数值类型做范围过滤的时候
GET /索引库名称/_search
{
"query": {
"range": {
"字段": {
#示例,此处写的是 大于和小于的条件范围
"gte": 10,
"lte": 20
}
}
}
}
4.2.4 地理坐标查询
#经纬度查询
GET /索引库名称/_search
{
"query": {
"geo_distance":{
"location":"先写纬度,再写经度",
"distance":"距离"
}
}
}
GET /索引库名称/_search
{
"query": {
"geo_distance":{
#location 还可以写成这样
"location":{
"lat":"纬度",
"lon":"经度"
},
"distance":"距离"
}
}
}
4.2.5 布尔查询
#布尔查询
GET /索引库名称/_search
{
"query": {
"bool": {
# must 必须匹配每个子查询,类似“与”
"must": [
{查询条件,此处可使用上述所有查询类型}
],
# must_not 必须不匹配,**不参与算分**,类似“非”
"must_not": [
{查询条件,此处可使用上述所有查询类型}
],
# should:选择性匹配子查询,类似“或”
"should": [
{查询条件,此处可使用上述所有查询类型}
],
# filter:必须匹配,**不参与算分**
"filter": [
{查询条件,此处可使用上述所有查询类型}
]
}
}
}
五. Java操作ES
注:本文ES版本为7.12.1,已无Type
1.环境准备
1.1 导入依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
1.2 修改ES版本
<elasticsearch.version>设置想要的版本</elasticsearch.version>
1.3 初始化RestHighLevelClient
该步骤仅做参考即可,可以有各种各样的方法初始化RestHighLevelClient
/**
* ES常量类
*/
public interface EsConstant {
String ES_URL = "配置ES的url常量";
String INDEX = "配置索引库名称常量";
String MAPPING = "配置Mapping常量";
}
/**
* 配置类
*/
@Configuration
public class EsConfig {
/**
* 将RestHighLevelClient的Bean交给Spring管理
* @return
*/
@Bean
public RestHighLevelClient client(){
return new RestHighLevelClient(RestClient.builder(HttpHost.create(EsConstant.ES_URL)));
}
}
2.索引库操作
2.1 创建索引库
示例:
//构造请求对象
CreateIndexRequest createIndexRequest = new CreateIndexRequest(EsConstant.INDEX);
//指定索引库映射条件
createIndexRequest.source(EsConstant.MAPPING, XContentType.JSON);
//创建索引库
CreateIndexResponse response = client.indices()
.create(createIndexRequest, RequestOptions.DEFAULT);
//这里可以对响应结果解析
String index = response.index();
boolean acknowledged = response.isAcknowledged();
//打印索引库名称和创建是否成功
System.out.println("index名称:" + index + "\n" + "acknowledged: " + acknowledged);
源码:
//参数一:创建索引库请求对象,
//参数二:此处写RequestOptions.DEFAULT 固定写法即可
//参数二内容可能为ES以后扩展所用的参数,所有方法中,含该参数都写固定写法即可
public CreateIndexResponse create(CreateIndexRequest createIndexRequest,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(createIndexRequest, IndicesRequestConverters::createIndex, options,
CreateIndexResponse::fromXContent, emptySet());
}
2.2 查询、删除索引库
示例:查询、删除索引库,除了API不一样,实现整体过程都类似
//构造查询请求对象
GetIndexRequest getIndexRequest = new GetIndexRequest(EsConstant.INDEX);
//查询索引库,client.indices().get()
client.indices().get(getIndexRequest , RequestOptions.DEFAULT);
//构造删除请求对象
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(EsConstant.INDEX);
//删除索引库,client.indices().delete()
client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
3.文档操作
3.1 基本操作
3.1.1 增加文档
//创建增加文档的请求对象
IndexRequest indexRequest = new IndexRequest(EsConstant.INDEX);
//设置文档ID和数据
indexRequest.id(文档对象ID.toString())
.source(JSONObject.toJSONString("文档对象"), XContentType.JSON);
//增加文档到索引库
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
3.1.2 根据id查询文档
//public GetRequest(String index, String id) 构造方法
//参数一 索引库 参数二 要查询的文档id
GetRequest getRequest = new GetRequest(EsConstant.INDEX, "文档id");
//查询文档
GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
//从response获取source转为对象
String json = response.getSourceAsString();
类 对象 = JSONObject.parseObject(json, 类.class);
3.1.3 更新文档
//1.获取要更新的对象
//2.创建更新文档的请求对象
//public UpdateRequest(String index, String id)
//参数一 索引库 参数二 要查询的文档id
UpdateRequest updateRequest = new UpdateRequest(EsConstant.INDEX, "待更新文档ID");
//3.通过doc方法设置更新文档
updateRequest.doc(json, XContentType.JSON);
//4.根据请求对象更新文档
UpdateResponse response = client.update(updateRequest, RequestOptions.DEFAULT);
3.1.4 删除文档
//创建删除文档的请求对象
//public DeleteRequest(String index, String id)
//参数一 索引库 参数二 要删除的文档id
DeleteRequest deleteRequest = new DeleteRequest(EsConstant.INDEX, "要删除的文档id");
//根据请求对象删除文档
DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT);
3.1.5 批量导入数据到索引库
//1.获取要导入的数据,一般为集合对象,示例 demolist
//2.构造BulkRequest
BulkRequest bulkRequest = new BulkRequest();
//3.将数据批量添加到请求对象中
for (Demo demo: demolist) {
bulkRequest.add(new IndexRequest(EsConstant.INDEX)
.id(demo.getId().toString())
.source(JSONObject.toJSONString(demo), XContentType.JSON));
}
//4.通过bulk方法批量添加数据
BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
3.2 查询操作
3.2.1 全文检索查询
(1). match_all()
//1.构建请求对象
SearchRequest searchRequest = new SearchRequest(EsConstant.INDEX);
//2.封装查询条件
searchRequest.source()
.query(QueryBuilders.matchAllQuery());
//3.执行查询
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
//4.解析结果
SearchHit[] hits = response.getHits().getHits();
//通过遍历hits数组可以输出文本内容
for (Object hit : hits) {
String json = hit.getSourceAsString();
Object object = JSONObject.parseObject(json, Object.class);
System.out.println(object);
}