Elasticsearch是一个开源的分布式搜索和分析引擎,用于存储、搜索和分析大量的数据。它构建在Apache Lucene库之上,提供了简单易用的RESTful API和丰富的查询语言,使用户可以轻松地进行实时数据索引、搜索和分析。
Elasticsearch的背景可以追溯到2010年,由Elastic公司(前称为Elasticsearch BV)创立,旨在解决传统关系型数据库无法处理海量数据和实时搜索的问题。它最初是作为全文搜索引擎的扩展功能而开发的,并迅速发展成为一种强大的分布式数据存储和分析解决方案。
Elasticsearch采用分布式架构,可以将数据分散存储在多个节点上,以实现高可用性和扩展性。它使用倒排索引技术来加速搜索过程,通过将每个唯一词项与包含该词项的文档关联起来,快速定位相关文档。同时,Elasticsearch还支持复杂的查询和聚合操作,如全文搜索、地理空间搜索、过滤器、排序、分组和统计等,使用户能够灵活地进行数据分析和挖掘。
除了强大的搜索和分析功能,Elasticsearch还具有以下特点:
实时性: Elasticsearch可以在数据写入后几乎立即对其进行索引和搜索,支持实时数据分析和监控。
可扩展性: 用户可以轻松地水平扩展Elasticsearch集群,通过添加更多的节点来处理大规模数据和高并发请求。
多种数据类型支持: Elasticsearch可以处理各种类型的数据,包括结构化数据、半结构化数据和非结构化数据。
强大的查询语言: Elasticsearch提供了丰富的查询语言,如全文查询、词项查询、范围查询、布尔查询等,支持复杂的条件和聚合操作。
易于集成: Elasticsearch与许多常见的数据存储和处理工具集成紧密,如Logstash(数据收集和转换)、Beats(数据采集)、Kibana(数据可视化)等。
由于其出色的性能和灵活性,Elasticsearch已经广泛用于各种应用场景,包括日志分析、实时监控、企业搜索、电子商务、安全分析、数据挖掘等。它被许多大型企业和组织采用,并成为当前最受欢迎的开源搜索和分析引擎之一。
搜索引擎:Elasticsearch提供强大的全文搜索功能,可以快速索引和搜索大量的结构化、半结构化和非结构化数据。它支持各种查询类型和复杂的搜索条件,满足实时搜索的需求。
日志和事件数据分析:Elasticsearch被广泛用于日志管理和分析。它能够接收和索引来自不同来源的日志数据,并支持实时的日志搜索和分析。通过使用Elastic Stack中的其他组件(如Logstash和Kibana),用户可以构建完整的日志分析解决方案。
实时监控和指标分析:Elasticsearch可以用于实时监控和分析系统的性能指标、日志和事件数据。它可以接收并索引来自多个来源的指标数据,并提供实时的仪表盘和可视化工具,帮助用户实时了解系统状态和性能。
企业搜索:Elasticsearch被广泛应用于企业搜索场景,如产品目录搜索、文档搜索和电子邮件搜索等。它可以处理大规模的文本数据集,并提供高效的全文搜索、自动完成和相关性排序等功能。
数据分析和挖掘:Elasticsearch支持各种聚合操作,如统计、分组、排序和桶分析等。这使得用户可以从大规模数据集中提取有价值的信息,进行深入的数据分析和挖掘。
分布式架构:Elasticsearch采用分布式架构,可以处理大规模数据和高并发请求。它将数据分散存储在多个节点上,并提供数据冗余备份,以实现高可用性和扩展性。
实时性:Elasticsearch支持实时索引和查询数据,可以几乎立即对写入的数据进行索引和搜索。这使得用户可以快速获得最新的数据结果,并进行实时监控和决策。
强大的查询语言:Elasticsearch提供丰富的查询语言,包括全文查询、词项查询、范围查询、布尔查询等。用户可以通过灵活的查询条件和过滤器来获取精确的搜索结果。
多样化的数据类型支持:Elasticsearch可以处理各种类型的数据,包括结构化数据、半结构化数据和非结构化数据。它能够自动推断字段类型,并提供相应的索引和搜索功能。
易于集成和扩展:Elasticsearch与许多常见的数据存储和处理工具紧密集成,如Logstash、Beats和Kibana。它还提供了灵活的RESTful API,方便与其他应用程序进行集成和扩展。
开源和活跃的社区支持:Elasticsearch是一个开源项目,拥有庞大的开发者社区。这意味着用户可以从社区中获取丰富的资源、文档和支持,并参与到项目的发展和改进中。
索引(Index):
操作演示:
PUT /my-index
文档(Document):
操作演示:
POST /my-index/_doc/1
{
"title": "Elasticsearch 介绍",
"content": "Elasticsearch 是一个开源的分布式搜索引擎,用于高效地存储、检索和分析数据。",
"timestamp": "2023-06-29T00:00:00"
}
类型(Type):
操作演示:
创建一个名为 “my-index” 的索引,并定义一个名为 “product” 的类型:
PUT /my-index
{
"mappings": {
"product": {
"properties": {
"name": { "type": "text" },
"price": { "type": "float" }
}
}
}
}
在 “my-index” 索引的 “product” 类型中创建一个名为 “1” 的文档:
PUT /my-index/product/1
{
"name": "iPhone",
"price": 999.99
}
从 Elasticsearch 7.x 版本开始,类型逐渐被废弃,推荐将数据以更细粒度的索引方式进行组织。
Elasticsearch 集群:
Elasticsearch 节点:
Elasticsearch 分片:
分片包括两种类型:
注意事项:
主分片(Primary Shard):
配置方法:
"number_of_shards"
来定义主分片的数量。PUT /my-index
{
"settings": {
"number_of_shards": 5
},
"mappings": {
...
}
}
副本分片(Replica Shard):
配置方法:
在创建索引时,可以通过设置参数 "number_of_replicas"
来定义副本分片的数量。
例如,创建一个具有 1 个副本分片的索引:
PUT /my-index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
...
}
}
可以动态调整索引的副本分片数量。例如,将索引的副本分片数量增加到 2:
PUT /my-index/_settings
{
"index": {
"number_of_replicas": 2
}
}
主分片和副本分片在 Elasticsearch 中起到不同的作用。主分片负责索引的写操作,而副本分片提供冗余、高可用性和读操作的支持。您可以在索引创建或动态修改过程中设置主分片和副本分片的数量,以满足您的需求。
Elasticsearch 是将搜索请求发送到整个集群中的各个节点,并通过倒排索引来快速找到匹配的文档。
倒排索引(Inverted Index):
分词器(Tokenizer)和分析器(Analyzer):
查询解析和查询语句:
倒排索引的匹配和评分:
结果排序和高亮显示:
分布式搜索:
Elasticsearch 能够快速而高效地进行全文搜索,并提供准确的搜索结果。对于大规模和复杂的数据集,它的搜索能力得到了有效的优化和扩展。
构建查询语句是使用 Elasticsearch 进行搜索的关键步骤之一。通过构建准确和灵活的查询语句,可以获得符合需求的搜索结果。
查询类型选择:
构建查询条件:
使用查询字符串(Query String):
使用 Query DSL:
添加过滤器(Filters):
使用聚合(Aggregations):
调整查询参数:
全文查询(Match Query):
{
"query": {
"match": {
"title": "Elasticsearch"
}
}
}
精确值查询(Term Query):
{
"query": {
"term": {
"category": "Technology"
}
}
}
范围查询(Range Query):
{
"query": {
"range": {
"price": {
"gte": 10,
"lte": 100
}
}
}
}
布尔查询(Bool Query):
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Elasticsearch" } },
{ "term": { "category": "Technology" } }
],
"must_not": { "term": { "status": "Archived" } }
}
}
}
高亮显示查询结果:
{
"query": {
"match": {
"content": "Elasticsearch"
}
},
"highlight": {
"fields": {
"content": {}
}
}
}
使用过滤器和聚合操作是进行高级搜索的重要手段。过滤器用于筛选搜索结果,而聚合操作用于分组、统计和计算搜索结果。
过滤器(Filters):
聚合操作(Aggregations):
通过使用过滤器和聚合操作,可以实现更精确的搜索和更深入的数据分析。可以根据具体需求来选择合适的过滤器类型和聚合操作,并根据数据结构和索引映射来构建高级搜索查询语句。
title
(商品标题)、price
(价格)和 category
(商品类别)。我们想要查询价格在 10 到 100 之间,并且类别为 “Technology” 的商品。{
"query": {
"bool": {
"filter": [
{
"range": {
"price": {
"gte": 10,
"lte": 100
}
}
},
{
"term": {
"category": "Technology"
}
}
]
}
}
}
在上述查询中,我们使用了 Bool 查询构造器来组合多个过滤器。range
过滤器用于筛选价格在指定范围内的商品,而 term
过滤器则用于筛选类别为 “Technology” 的商品。该查询返回的结果将只包含满足这两个条件的商品文档。
{
"aggs": {
"category_count": {
"terms": {
"field": "category",
"size": 10,
"order": {
"_count": "desc"
}
}
}
}
}
在上述聚合操作中,我们使用了 Terms 聚合操作来按照 category
字段对商品进行分组,并计算每个分类的文档数量。size
参数指定了返回的分组数量上限,而 order
参数以文档数量 _count
字段的降序进行排序。该查询将返回按照商品类别分组后的结果,其中每个分组都包含类别和对应的商品数量。
在 Elasticsearch 中,映射(Mapping)是用于定义文档如何存储和索引的过程。它决定了文档中的字段及其属性,例如数据类型、分词器、索引设置等。映射在建立索引之前定义,并且在索引过程中将其应用于文档,以便 Elasticsearch 能够正确地解析和处理文档的内容。
映射的作用包括:
定义字段类型:
text
类型,用于全文搜索,或者定义为 keyword
类型,用于精确匹配和聚合操作。配置分词器:
standard
分词器,而为中文字段指定 smartcn
分词器。索引控制:
动态映射:
通过映射,我们可以灵活地定义文档结构和字段属性,以满足特定的搜索和分析需求。良好的映射设计可以提高搜索性能、减少存储空间,并确保数据的一致性和准确性。在建立索引之前,仔细考虑和定义映射是非常重要的。
以下是一个示例,展示了如何定义一个映射来索引包含不同类型字段的文档:
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"price": {
"type": "float"
},
"category": {
"type": "keyword"
},
"description": {
"type": "text",
"analyzer": "english"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
在上述示例中:
my_index
的索引,并指定了其映射。properties
对象用于定义索引中的字段和其属性。title
字段被定义为 text
类型,可以用于全文搜索。price
字段被定义为 float
类型,可以用于数值排序和统计。category
字段被定义为 keyword
类型,用于精确匹配和聚合操作。description
字段被定义为 text
类型,并指定了分词器 english
,用于英文文本的处理。created_at
字段被定义为 date
类型,并指定了日期格式。通过这样的映射定义,当我们索引文档时,Elasticsearch 将根据映射来解析和处理各个字段的内容,并构建适合搜索和分析的倒排索引结构。这使得我们可以使用各种查询和聚合操作来搜索、过滤和分析文档中的数据。
使用分析器是 Elasticsearch 中进行文本处理和搜索优化的关键步骤之一。分析器负责将文本转换为有意义的词条,以便能够进行有效的搜索和分析。
了解分析器的类型:
Elasticsearch 提供了多种类型的分析器,每个分析器都有不同的用途和效果。
创建索引时定义分析器:
在创建索引时,可以通过指定 mappings
字段来定义分析器。在字段的映射中,使用 analyzer
属性来指定要使用的分析器。
{
"mappings": {
"properties": {
"field_name": {
"type": "text",
"analyzer": "analyzer_name"
},
...
}
}
}
field_name
:要应用分析器的字段名称。type
:字段类型,通常为 text
。analyzer_name
:要使用的分析器的名称。动态映射和自动应用分析器:
默认情况下,Elasticsearch 在创建索引时会根据字段的数据类型自动应用相应的分析器。例如,对于 text
类型的字段,将自动应用默认的标准分析器。这是通过动态映射实现的。
明确指定分析器:
如果你想显式地指定要使用的分析器,可以在查询或索引文档时使用 _analyze
API 来手动应用分析器。
GET /my_index/_analyze
{
"analyzer": "analyzer_name",
"text": "your_text_to_analyze"
}
analyzer_name
:要使用的分析器的名称。your_text_to_analyze
:要进行分析的文本。分词器和过滤器:
分析器由分词器(Tokenizer)和过滤器(Filter)组成。分词器负责将文本拆分成单独的词条,而过滤器则对词条进行进一步的处理,如删除停用词、词干提取、大小写转换等。
自定义分析器:
如果预定义的分析器无法满足特定需求,你可以构建自定义分析器。自定义分析器可以包含一个或多个分词器和过滤器,以便根据需要进行文本处理。
查看分析结果:
在使用分析器时,你可以使用 _analyze
API 来查看分析结果,以确保分析器正常工作并生成预期的词条。
更新分析器:
如果已经创建了索引,但想要更改字段的分析器,需要重新创建索引或使用 Elasticsearch 的 Reindex API 将文档从旧索引重新索引到新索引中。
通过使用适当的分析器和配置,可以实现更好的搜索效果和更准确的文本分析。请根据具体需求选择合适的分析器,并确保对分析结果进行验证和测试。
假设我们有一个索引,用于存储产品信息,并且想要对产品的描述字段进行文本处理和搜索优化。我们将使用标准分析器来演示。
创建索引时定义分析器:
我们可以在创建索引时为描述字段指定使用的分析器。
PUT /products
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "standard"
}
}
}
},
"mappings": {
"properties": {
"description": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
在上述示例中,我们定义了一个名为 my_analyzer
的标准分析器,并将其应用于 description
字段。
插入文档:
现在,我们可以插入一些文档到 products
索引中,包含产品的描述信息。
POST /products/_doc/1
{
"description": "这是一个高质量的耳机,具有优秀的音质和舒适的佩戴体验。"
}
POST /products/_doc/2
{
"description": "这款电视屏幕尺寸大,画质清晰逼真,适合观看电影和玩游戏。"
}
搜索文档:
现在,我们可以使用搜索查询来搜索具有特定关键字的产品描述。
GET /products/_search
{
"query": {
"match": {
"description": "电视"
}
}
}
上述搜索查询将返回含有关键字 “电视” 的产品描述。
API名称和端点:
请求方法:
请求参数:
响应结果:
示例请求和响应:
{
"cluster_name": "my_cluster",
"status": "green",
"timed_out": false,
"number_of_nodes": 5,
"number_of_data_nodes": 3,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100.0
}
通过使用集群健康API,您可以定期调用该API以获取关于集群的实时状态信息。这有助于监控集群运行状况、检测潜在问题并及时采取行动。您还可以基于集群健康的状态定义警报规则,以便在集群出现问题时及时通知负责人员。
配置日志文件:
要配置日志文件,需要修改Elasticsearch的配置文件,该文件位于config
目录下。默认情况下,配置文件名为elasticsearch.yml
。
elasticsearch.yml
文件。info
,可以根据需要更改为debug
、warn
或error
等级别。path.logs
配置项,设置日志文件的输出路径。可以指定完整路径,或者使用相对于ES_HOME
(Elasticsearch安装目录)的路径。查看日志文件:
日志文件位于指定的输出路径,默认为logs
目录。您可以通过以下方式查看日志文件:
cat
、tail
等)来查看日志文件,例如:cat path/to/logfile.log
。日志文件的类型:
Elasticsearch生成多个日志文件,其中包括:
日志文件的轮转和归档:
Elasticsearch支持日志文件的轮转和归档,以便管理和维护日志文件的大小和数量。可以使用第三方的日志轮转工具(如logrotate
)来完成此任务,并在配置文件中指定轮转的规则和频率。
例如,使用logrotate
工具,在/etc/logrotate.d
目录下创建一个名为elasticsearch
的配置文件,并添加以下内容:
/path/to/elasticsearch/logs/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
}
这将每天轮转一次日志文件,并保留最近的7个归档文件。
通过配置和查看日志文件,您可以及时获取Elasticsearch集群的运行状态、故障信息和性能问题,有助于排查和解决各种问题,并确保集群的顺利运行。
假设我们有一个电商平台,用户可以通过搜索框来搜索商品,并根据他们的行为历史和喜好,我们也希望能够向他们推荐相关的商品。
步骤1: 数据准备
首先,我们需要准备商品数据。假设我们有以下三个商品的数据:
步骤2: 索引和映射设置
接下来,我们需要创建一个索引,并定义映射设置,以便Elasticsearch知道如何处理我们的商品数据。我们将使用Elasticsearch的Index API和Mapping API来完成这一步。
下面是一个使用CURL命令创建索引和定义映射的示例:
PUT /products
{
"mappings": {
"properties": {
"name": {"type": "text"},
"description": {"type": "text"},
"price": {"type": "float"},
"brand": {"type": "keyword"},
"category": {"type": "keyword"}
}
}
}
在上述示例中,我们使用PUT请求创建了一个名为"products"的索引,并指定了每个字段的数据类型。
步骤3: 数据导入
接下来,我们将商品数据导入到Elasticsearch索引中。我们可以使用Elasticsearch的Index API来完成这一步。
下面是一个使用CURL命令将每个商品文档导入到"products"索引的示例:
POST /products/_doc/1
{
"name": "iPhone 12",
"description": "Apple 最新款智能手机",
"price": 9999,
"brand": "Apple",
"category": "手机"
}
POST /products/_doc/2
{
"name": "Samsung Galaxy S21",
"description": "三星旗舰智能手机",
"price": 8999,
"brand": "Samsung",
"category": "手机"
}
POST /products/_doc/3
{
"name": "Sony WH-1000XM4",
"description": "无线降噪耳机",
"price": 1999,
"brand": "Sony",
"category": "耳机"
}
在上述示例中,我们使用POST请求将每个商品文档导入到"products"索引中,每个文档都有一个唯一的标识符(例如1、2、3)。
步骤4: 商品搜索接口
现在,我们准备好进行商品搜索。我们将使用Elasticsearch的Search API来执行搜索请求。
下面是一个使用CURL命令进行商品搜索的示例:
GET /products/_search
{
"query": {
"match": {
"name": "iphone"
}
}
}
在上述示例中,我们使用GET请求执行了一个商品搜索请求,查询包含"iphone"关键字的商品名称。
步骤5: 查询构建和商品搜索
接下来,让我们使用Java代码来构建并执行相同的商品搜索请求。我们将使用Elasticsearch的Java High-Level REST Client来实现。
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
public class ElasticsearchProductSearchExample {
private static final String INDEX_NAME = "products";
private static final String HOSTNAME = "localhost";
private static final int PORT_NUMBER = 9200;
public static void main(String[] args) {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost(HOSTNAME, PORT_NUMBER, "http")));
try {
// 构建商品搜索请求
SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", "iphone");
searchSourceBuilder.query(matchQuery);
searchRequest.source(searchSourceBuilder);
// 执行商品搜索请求
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 处理商品搜索结果
searchResponse.getHits().forEach(hit -> {
System.out.println(hit.getSourceAsString());
});
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
在上述Java代码示例中,我们创建了一个RestHighLevelClient
实例,并指定Elasticsearch主机的主机名和端口号。
我们使用SearchRequest
和SearchSourceBuilder
来构建商品搜索请求。在商品搜索请求中,我们使用MatchQueryBuilder
指定查询关键字并设置要在哪个字段上执行。
使用client.search
方法来执行商品搜索请求,并使用SearchResponse
处理搜索结果。
步骤6: 商品推荐接口
除了商品搜索,我们还希望能够向用户推荐相关的商品。为此,我们可以使用Elasticsearch的推荐功能。具体来说,我们可以使用基于用户历史行为的协同过滤推荐算法来推荐商品。
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
public class ElasticsearchProductRecommendationExample {
private static final String INDEX_NAME = "products";
private static final String HOSTNAME = "localhost";
private static final int PORT_NUMBER = 9200;
public static void main(String[] args) {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost(HOSTNAME, PORT_NUMBER, "http")));
try {
// 构建商品推荐请求
SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("category", "手机");
searchSourceBuilder.query(matchQuery);
searchSourceBuilder.size(5); // 限制结果数量为5个
searchRequest.source(searchSourceBuilder);
// 执行商品推荐请求
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 处理商品推荐结果
searchResponse.getHits().forEach(hit -> {
System.out.println(hit.getSourceAsString());
});
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
在上述Java代码示例中,我们使用相同的步骤来创建和关闭RestHighLevelClient
实例。
我们使用SearchRequest
和SearchSourceBuilder
来构建商品推荐请求。在商品推荐请求中,我们使用MatchQueryBuilder
指定查询的条件(例如商品类别为手机)。
此外,我们可以使用searchSourceBuilder.size
方法限制结果数量,以便只返回若干个推荐商品。
使用client.search
方法来执行商品推荐请求,并使用SearchResponse
处理搜索结果。