随着数据量的不断增长,搜索和分析大规模数据集变得越来越重要。传统数据库在面对这种需求时往往表现不佳,这时候就需要一种专门用于搜索和分析的引擎。ElasticSearch (简称ES)就是这样一款强大的搜索引擎,它具有许多优势,使得它成为许多企业和开发者的首选。
简单的说:ElasticSearch
是一个实时的分布式存储、搜索、分析的引擎
在我看来ES最强的其实是它的模糊搜索功能。
那有的人就会问了:我数据库一样可以实现模糊搜索啊?
select * from student where name like '%宁正%'
例如这个sql就可以查出姓名中带有宁正两字的学生
的确,这这样做是可以模糊搜索的,但是name like '%宁正%'
这种写法它是不走索引的,所以就意味着:如果你的数据量很大比如上千万,上亿条,那你不管如果去优化代码,你的查询也肯定是秒级的
并且还有一个情况,我们大部分搜索的时候,输入的信息其实并不是很准确,例如我想搜索ElasticSearch
有关的信息,但我一不小心打成了ElesticSearch
,如果按sql语句去进行模糊搜索你就无法找到和es有关的信息
所以在这种情况就可以使用ElasticSearch
,它就是为了搜索而生的。
因此,我这边就把es的优点罗列出来,并进行浅显的分析:
ES对于全文的模糊搜索非常擅长
原因:ES是基于倒排索引,使得ES能够快速匹配关键字并返回相关结果,而不需要像传统数据库那样进行全表扫描。倒排索引在存储和查询大规模文本数据时具有较高的效率。
那有些小伙伴看了可能就会问了:倒排索引是什么?倒排索引和正排索引有什么区别?我们日常使用的数据库可以使用倒排索引吗?
那接下来就一个一个回答:
倒排索引是一种基于关键词的索引结构,常用于全文搜索引擎和信息检索系统中。它是一种将文档中的关键词映射到对应的文档ID的数据结构。
具体来说,倒排索引将文档中的每个关键词与包含该关键词的文档ID建立映射。对于每个关键词,倒排索引记录了出现该关键词的文档列表,包括它们的词频、位置等信息。这使得在给定关键词的情况下,可以快速找到包含该关键词的相关文档。
正排索引是一种文档ID进行排序的索引结构,它存储了文档和文档中的每个词条的详细信息。
我有一个通俗易懂的方法来表达:
正排索引就想我们看书时的目录,可以直接通过页码找到对应页码的内容
而倒排索引就是将整本书中的词汇提取出来,并记录改词汇存在于哪些页码中,形成映射关系,当我想要查找一个词汇出现在哪些页中时,便只要根据这个映射表就可以快速找到想要的页数
这么一解释,大家应该就清楚了。
实际上,数据库是可以支持倒排索引的,但是与传统的正排索引相比,数据库倒排索引的实现相对有些复杂,而且数据库的主要设计目标是支持高效的数据管理和事务处理,而不是专注于全文搜索等复杂的查询需求
ES的查询语法更灵活,可以精确控制查询条件和权重,以及进行更复杂的模糊搜索
Elasticsearch的查询语法相当灵活,可以根据需要控制查询条件和权重,以及执行诸如布尔查询、范围查询、模糊查询,地理位置等复杂查询。通过使用查询语法,可以实现更精确的搜索。
我这边写一个基于自身地理位置查询的一个demo
geoDistanceQuery
是一种地理位置查询,用于查询距离某个地理坐标点一定距离范围内的文档。只需要提供一个地理点的经纬度坐标和一个距离,以及一个单位:
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
GeoDistanceQueryBuilder geoQuery = QueryBuilders.geoDistanceQuery("local")
.point(lat, lon) // 地理位置坐标
.distance(distance, DistanceUnit.KILOMETERS); // 查询距离
sourceBuilder.query(geoQuery);
SearchRequest searchRequest = new SearchRequest("indexName");
searchRequest.source(sourceBuilder);
// 执行查询
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
在上面的demo中,我们创建了一个geoDistanceQuery
来查询location字段在给定地理位置坐标的一定距离范围内的文档。这里使用的是公里作为单位。
ES提供了丰富的聚合和分析功能
ES原生的提供了丰富的聚合和分析功能,可以对结果进行聚合、分组、排序等多种操作,并且ES还提供了许多其他的分析功能,如词频统计、日期直方图等。这些功能可以帮助用户更深入地理解数据,生成仪表板和可视化图表。
我在这边也写一个较为简单的demo,看一看就好,详细的之后的博客会讲解
假设我们有一个索引存储了电影信息,包含字段:title(电影标题)、genre(电影类型)和rating(电影评分)。
现在,我们希望对不同类型的电影进行聚合,并计算每个类型的平均评分。
首先,我们需要构建一个聚合查询,指定按genre字段进行分组,并计算每个分组的平均值。
GET movies/_search
{
"size": 0,
//指定聚合操作的容器
"aggs": {
//聚合操作起的一个名字
"genres": {
//指定分组字段的聚合操作类型
"terms": {
// 指定要分组的字段
"field": "genre"
},
"aggs": {
//平均值聚合操作起的一个名字
"avg_rating": {
//计算均值的聚合操作类型
"avg": {
//操作的字段
"field": "rating"
}
}
}
}
}
}
在上面的查询中,我们使用terms
聚合将电影按照genre
字段进行分组,并使用avg
聚合计算每个分组的rating
字段的平均值。
就会得到以下类似的结果:
"aggregations" : {
"genres" : {
"buckets" : [
{
"key" : "Action",
"doc_count" : 100,
"avg_rating" : {
"value" : 4.2
}
},
{
"key" : "Drama",
"doc_count" : 80,
"avg_rating" : {
"value" : 3.8
}
},
...
]
}
}
Action类的电影有100部平均评分4.2, Drama类的电影有80部平均评分3.8
这只是聚合和分析功能的一个简单示例,实际上ES提供了更多丰富的聚合操作和分析功能,可以根据具体需求进行更复杂的操作
ES分布式架构在水平扩展上的表现出色,通过将数据分片存储在多个节点上,ES可以处理大规模数据,并且能够通过并行化查询和分布式计算来提高查询性能。
这个在这就不细讲了,之后具体介绍的是会讲述。
第一个问题的回答,显而易见的当然是不能无脑上ES!
第二个问题,那我们什么时候才要用ES呢?
在我看来可以从以下几个方法来考虑:
所以不要因为这个技术比较厉害就无脑的去使用该技术,在使用技术的时候也要考虑到它所带来的风险