elasticsearch作为一个开源的检索引擎产品,继续分析其关键概念、原理和应用场景。
ELK 技术栈,包括Elasticsearch、Kibana和Logstash,能够安全可靠的获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。
1、Elasticsearch
一个开源的、分布式、实时分析搜索引擎,建立在全文搜索引擎库 Apache Lucene 基础上,同时隐藏了 Apache Lucene 的复杂性。Elasticsearch 将所有的功能打包成一个独立的服务,并提供了一个简单的 RESTful API 接口。
2、Kibana
一个开源和免费的工具,Kibana 可以为 Logstash 和 Elasticsearch 提供图形化的日志分析 Web 界面,可以汇总、分析和搜索重要数据日志。
3、Logstach
一个完全开源的工具,主要用于日志收集,同时可以对数据处理,并输出给 Elasticsearch。 Logstash 只做三件事情:数据输入、数据加工(如过滤,改写等) 以及数据输出。
4、Lucene
一个Apache软件基金会Jakarta项目组的一个子项目,提供了简单却强大的应用程序接口,能够全文索引和搜索。Java开发环境中Lucene是成熟的免费开源工具,但Lucene只是一个提供全文搜索功能类库的核心工具包。
Elasticsearch是面向文档型数据库,一条数据就是一个文档,和关系型数据库mysql的类比如下
其中Types概念已经弱化了,在ES6中,一个index下已经只能包含一个type,ES7中Types的概念已经被删除。
1、倒排索引
Elasticsearch 使用一种称为倒排索引的结构,它适用于快速的全文搜索。
正向索引,就是搜索引擎会将待搜索的文件都对应一个文件 ID,搜索时将这个ID 和搜索关键字进行对应,形成 K-V 对,然后对关键字进行统计计数排名 ,类似如下
倒排索引, 搜索引擎会将正向索引重新构建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词,类似如下
示例:
2、分词器
将一块文本分成适合于倒排索引的独立的词条,将这些词条统一化为标准格式以提高它们的“可搜索性”。
常见分词器有标准分词器、简单分析器、空格分析器等,对中文支持较好的为IK分词器。
Logstach收集日志,并存放到Elasticsearch 集群中,而 Kibana 则 从 ES 群集中查询数据生成图表,再返回给 Browser。
1、收集日志
2、将日志通过Logstach转存到Elasticsearch
3、利用Elasticsearch 对格式化后的日志数据进行创建索引和存储
4、 前端数据的展示(Kibana)
ES中的操作流程:
1、通过ES提供的API创建索引
2、通过ES提供的API对上游处理后的Document集合存入ES
3、通过ES提供的API实现全文检索
4、ES返回命中的Document对象集合,包含命中次数、命中的Document
ES提供了对索引、文档的维护操作,包括新增、修改、删除、查询。在利用ES检索引擎的检索能力的前提是对指定的日志文件创建索引并对格式化数据后存入ES。其中,Document就好比日志文件中的一条日志记录。
四、springboot+elasticsearch实例
1、新建springboot工程,添加elasticsearch相关组件,pom如下
org.springframework.boot
spring-boot-starter-parent
2.2.6.RELEASE
1.8
org.springframework.boot
spring-boot-starter-data-elasticsearch
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
2、applicaton.properties配置elasticsearch
elasticsearch.host=127.0.0.1
elasticsearch.port=9200
3、elasticsearch配置类
ElasticsearchRestTemplate和spring中其他template类似,是elasticsearch包中封装好的一个类。在最新的版本中,ElasticsearchRestTemplate替代了原来的ElasticsearchTemplate,原因是ElasticsearchTemplate基于TransportClient,而TransportClient在8.x以上版本中移除,所以推荐直接使用ElasticsearchRestTemplate。ElasticsearchRestTemplate是基于RestHighLevelClient客户端的,需要自定义配置类,继承AbstractElasticsearchConfiguration并实现elasticsearchClient抽象方法,创建返回RestHighLevelClient对象。
@Configuration
@Data
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
@Value("${elasticsearch.host}")
private String host ;
@Value("${elasticsearch.port}")
private Integer port ;
@Override
public RestHighLevelClient elasticsearchClient() {
RestClientBuilder builder = RestClient.builder(new HttpHost(host, port));
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
return restHighLevelClient;
}
}
4、实体类,映射索引和文档
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "log_index", type = "log_type", shards = 2, replicas = 1)//映射到ES,表示此类是product索引的映射,主分片3个,副本1个,每个主片,都有一个副本
public class EsLog {
/**
* id 是全局唯一的标识,等同于 es 中的"_id"
*/
@Id
private Long id;
/**
* 是否索引: 看该域是否能被搜索, index = true(默认为true)
* 是否分词: 表示搜索的时候是整体匹配还是单词匹配,Keyword不进行分词,Text进行分词
*/
@Field(type = FieldType.Keyword)
private String time;
/**
* 是否索引: 看该域是否能被搜索, index = true(默认为true)
* 是否分词: 表示搜索的时候是整体匹配还是单词匹配,Keyword不进行分词,Text进行分词
*/
@Field(type = FieldType.Text, analyzer = "ik_smart", searchAnalyzer = "ik_smart")
private String content;
}
5、ES持久层接口
@Repository
public interface EsLogRepository extends ElasticsearchRepository {
}
6、控制层接口
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Autowired
private EsLogRepository esLogRepository;
@GetMapping("createIndex")
public Object createIndex() {
// 系统初始化会自动创建索引
return "ok";
}
@GetMapping("deleteIndex")
public Object deleteIndex() {
boolean flag = elasticsearchRestTemplate.deleteIndex(EsLog.class);
return flag;
}
@GetMapping("insertDocument")
public Object insertDocument() {
EsLog esLog = new EsLog(11L,"20220601", "Root WebApplicationContext: initialization completed in 1097 ms");
EsLog save = esLogRepository.save(esLog);
return save;
}
@GetMapping("updateDocument")
public Object updateDocument() {
EsLog esLog = new EsLog(1L,"20220601", "Root WebApplicationContext: initialization completed in 1097 ms. This is es world");
EsLog save = esLogRepository.save(esLog);
return save;
}
@GetMapping("getDocument")
public Object getDocument() {
EsLog esLog = esLogRepository.findById(1L).get();
return esLog;
}
@GetMapping("deleteDocument")
public Object deleteDocument() {
esLogRepository.deleteById(1L);
return "ok";
}
@GetMapping("insertBatch")
public Object insertBatch() {
List esLogList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
EsLog esLog = new EsLog((long) i,"20220601", "content" + i);
esLogList.add(esLog);
}
Iterable esLogs = esLogRepository.saveAll(esLogList);
return esLogs;
}
@GetMapping("getAllDocument")
public Object getAllDocument() {
Iterable esLogs = esLogRepository.findAll();
return esLogs;
}
@PostMapping("search")
public Object search(@RequestBody Map params) {
SearchQuery searchQuery= getQueryBuilder(params);
List esLogList = elasticsearchRestTemplate.queryForList(searchQuery, EsLog.class);
return esLogList;
}
public SearchQuery getQueryBuilder(Map params) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("content", params.get("content").toString());
// 分页
PageRequest pageable = PageRequest.of(0, 10);
// 排序
SortBuilder sort = SortBuilders.fieldSort("time").order(SortOrder.DESC);
//设置高亮效果
String preTag = "";
String postTag = "";
HighlightBuilder.Field highlightFields = new HighlightBuilder.Field("content").preTags(preTag).postTags(postTag);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchQueryBuilder)
.withPageable(pageable)
.withSort(sort)
.withHighlightFields(highlightFields)
.build();
return searchQuery;
}
7、测试结果
启动服务后自动创建索引
添加文档,如下
在Elasticsearch-head查看,如下
修改文档,如下
查看文档,如下
批量插入,如下
查看所有文档,如下
在Elasticsearch-head查看,如下
检索,如下