Elasticsearch学习总结(一)

Elasticsearch是一个分布式搜索引擎,其核心概念包括索引、文档、字段、分片和副本。索引是数据存储单位,文档是基本数据单元,字段定义文档属性。分片和副本支持大规模数据和高可用性。通过RESTAPI进行操作,支持搜索、聚合等高级功能。
摘要由CSDN通过智能技术生成

ES基本概念

以下是ES中一些重要的概念:

  • 索引(Index):索引是ES中最基本的数据存储单位,类似于关系型数据库中的表。每个索引可以包含多个文档(Document),每个文档可以包含多个字段(Field)。
  • 文档(Document):文档是ES中的基本数据单元,类似于关系型数据库中的一行数据。每个文档都有一个唯一的ID,可以通过ID来访问文档。
  • 字段(Field):字段是文档中的一个属性,类似于关系型数据库中的一列数据。每个字段都有一个数据类型和属性,如文本、数字、日期、地理位置等。
  • 分片(Shard):为了支持大规模数据存储和分布式搜索,ES将每个索引分成多个分片,每个分片可以存储一部分数据。分片可以分布在不同的节点上,从而实现数据的分布式存储和搜索。
  • 副本(Replica):为了提高搜索性能和数据可靠性,ES可以将每个分片复制多个副本,每个副本可以存储一份完整的数据。副本可以分布在不同的节点上,从而实现数据的高可用和负载均衡。
  • 映射(Mapping):映射定义了索引中每个字段的数据类型和属性,包括文本、数字、日期、地理位置等。映射可以帮助ES更好地理解数据,从而实现更精确的搜索和聚合。
  • 查询(Query):查询是ES中最基本的搜索操作,可以通过查询语句来搜索索引中的文档。ES支持多种查询类型,包括全文搜索、精确匹配、范围查询、聚合查询等。
  • 聚合(Aggregation):聚合是ES中的高级搜索操作,可以对搜索结果进行统计和分析。ES支持多种聚合类型,包括分组、统计、嵌套、过滤等。
  • 集群(Cluster):ES中的多个节点可以组成一个集群,集群中的节点可以相互通信和协作,从而实现数据的分布式存储和搜索。集群中的节点可以动态地加入和退出,从而实现集群的扩展和缩小。
  • 节点(Node):ES集群中的每个服务器都是一个节点,每个节点都有一个唯一的名称,可以通过名称来访问节点。
  • RESTAPI:ES提供了基于REST的API,可以通过HTTP协议来访问ES集群。通过API,可以进行索引、搜索、聚合、映射等操作,也可以管理集群、节点、分片等元数据。

ES架构

ES(Elasticsearch)的架构是分布式的,可以通过多个节点组成一个集群,实现数据的分布式存储和搜索。ES的架构包括以下几个组件:

  • 节点(Node):ES集群中的每个服务器都是一个节点,每个节点都有一个唯一的名称,可以通过名称来访问节点。每个节点都可以存储数据、执行搜索和聚合操作。
  • 索引(Index):索引是ES中最基本的数据存储单位,类似于关系型数据库中的表。每个索引可以包含多个文档(Document),每个文档可以包含多个字段(Field)。
  • 分片(Shard):为了支持大规模数据存储和分布式搜索,ES将每个索引分成多个分片,每个分片可以存储一部分数据。分片可以分布在不同的节点上,从而实现数据的分布式存储和搜索。
  • 副本(Replica):为了提高搜索性能和数据可靠性,ES可以将每个分片复制多个副本,每个副本可以存储一份完整的数据。副本可以分布在不同的节点上,从而实现数据的高可用和负载均衡。
  • 集群(Cluster):ES中的多个节点可以组成一个集群,集群中的节点可以相互通信和协作,从而实现数据的分布式存储和搜索。集群中的节点可以动态地加入和退出,从而实现集群的扩展和缩小。
  • 映射(Mapping):映射定义了索引中每个字段的数据类型和属性,包括文本、数字、日期、地理位置等。映射可以帮助ES更好地理解数据,从而实现更精确的搜索和聚合。
  • 查询(Query):查询是ES中最基本的搜索操作,可以通过查询语句来搜索索引中的文档。ES支持多种查询类型,包括全文搜索、精确匹配、范围查询、聚合查询等。
  • 聚合(Aggregation):聚合是ES中的高级搜索操作,可以对搜索结果进行统计和分析。ES支持多种聚合类型,包括分组、统计、嵌套、过滤等。
  • RESTAPI:ES提供了基于REST的API,可以通过HTTP协议来访问ES集群。通过API,可以进行索引、搜索、聚合、映射等操作,也可以管理集群、节点、分片等元数据。

ES的架构是高度可扩展和可靠的,可以支持大规模数据存储和分布式搜索。通过分片和副本的机制,可以实现数据的高可用和负载均衡。通过集群的机制,可以实现集群的扩展和缩小。ES(Elasticsearch)的架构是分布式的,可以通过多个节点组成一个集群,实现数据的分布式存储和搜索。

ES的API

Elasticsearch提供了丰富的API,包括以下几类:

索引API:用于创建、更新和删除索引,例如:
PUT /my_index:创建一个名为my_index的索引
DELETE /my_index:删除名为my_index的索引
文档API:用于创建、更新和删除文档,例如:
PUT /my_index/_doc/1:在my_index索引中创建一个ID为1的文档
GET /my_index/_doc/1:获取my_index索引中ID为1的文档
DELETE /my_index/_doc/1:删除my_index索引中ID为1的文档
搜索API:用于搜索文档,例如:
GET /my_index/_search?q=keyword:在my_index索引中搜索包含keyword的文档
POST /my_index/_search:使用查询DSL在my_index索引中搜索文档
聚合API:用于对搜索结果进行聚合操作,例如:
POST /my_index/_search:使用聚合DSL在my_index索引中对搜索结果进行聚合操作
管理API:用于管理Elasticsearch集群和节点,例如:
GET /_cat/health:获取集群健康状态
GET /_cat/nodes:获取集群节点信息
以上只是API的一部分,Elasticsearch还提供了许多其他API,如索引别名API、索引模板API、快照和恢复API等。

JAVA调用ES的部分API

Java可以使用Elasticsearch官方提供的Java客户端API来操作Elasticsearch。以下是使用Java API进行索引、文档和搜索操作的示例:

  • 创建索引
RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(new HttpHost("localhost", 9200, "http")));

CreateIndexRequest request = new CreateIndexRequest("my_index");
client.indices().create(request, RequestOptions.DEFAULT);
  • 创建文档
IndexRequest request = new IndexRequest("my_index");
request.id("1");
String jsonString = "{" +
        "\"user\":\"John\"," +
        "\"message\":\"hello world\"" +
        "}";
request.source(jsonString, XContentType.JSON);

IndexResponse response = client.index(request, RequestOptions.DEFAULT);
  • 搜索文档
SearchRequest request = new SearchRequest("my_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("message", "hello"));
request.source(sourceBuilder);

SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
    String sourceAsString = hit.getSourceAsString();
    System.out.println(sourceAsString);
}

以上示例中,我们使用了RestHighLevelClient来创建客户端,然后使用indices()、index()和search()等方法来操作索引、文档和搜索。

  • 聚合操作
SearchRequest request = new SearchRequest("my_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_user").field("user");
sourceBuilder.aggregation(aggregation);
request.source(sourceBuilder);

SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Terms terms = response.getAggregations().get("by_user");
for (Terms.Bucket bucket : terms.getBuckets()) {
    String keyAsString = bucket.getKeyAsString();
    long docCount = bucket.getDocCount();
    System.out.println(keyAsString + " " + docCount);
}

以上示例中,我们使用AggregationBuilders来创建聚合操作,然后将聚合操作添加到SearchSourceBuilder中,最后执行搜索操作并获取聚合结果

  • 管理操作
RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(new HttpHost("localhost", 9200, "http")));

ClusterHealthRequest request = new ClusterHealthRequest();
ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT);
String clusterName = response.getClusterName();
int numberOfNodes = response.getNumberOfNodes();
int numberOfDataNodes = response.getNumberOfDataNodes();
System.out.println(clusterName + " " + numberOfNodes + " " + numberOfDataNodes);

以上示例中,我们使用client.cluster()来获取ClusterClient,然后使用health()方法来获取集群健康状态。

需要注意的是,RequestOptions.DEFAULT参数同样是必须的。(官方推荐)

JAVA操作ES常见的问题以及解决方法

连接超时或请求超时

解决方法:可以通过设置RestClientBuilder的setRequestConfigCallback方法来设置请求超时时间和连接超时时间。例如:

RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
builder.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder
        .setConnectTimeout(5000)
        .setSocketTimeout(60000));
RestHighLevelClient client = new RestHighLevelClient(builder);

索引不存在或者文档不存在

解决方法:在进行索引或文档操作之前,可以先使用IndicesExistsRequest或GetRequest方法检查索引或文档是否存在。例如:

IndicesExistsRequest request = new IndicesExistsRequest("my_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
if (exists) {
    // 索引存在,进行操作
} else {
    // 索引不存在,进行处理
}

GetRequest request = new GetRequest("my_index", "_doc", "1");
boolean exists = client.exists(request, RequestOptions.DEFAULT);
if (exists) {
    // 文档存在,进行操作
} else {
    // 文档不存在,进行处理
}

搜索结果不准确或不完整

可以通过设置SearchSourceBuilder的size和from方法来控制搜索结果的数量和起始位置。例如:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(10); // 搜索结果数量为10
sourceBuilder.from(20); // 搜索结果起始位置为20

此外,还可以通过设置SearchSourceBuilder的trackTotalHits方法来控制是否返回搜索结果的总数量。默认情况下,Elasticsearch会返回搜索结果的总数量,但是在搜索结果很大的情况下,这可能会影响性能。如果只需要获取部分搜索结果,可以将trackTotalHits设置为false。例如:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.trackTotalHits(false); // 不返回搜索结果的总数量

聚合结果不正确

解决方法:在使用聚合操作时,需要注意聚合操作的嵌套顺序和参数设置。例如,在使用TermsAggregationBuilder时,需要设置field参数来指定要聚合的字段,否则聚合结果可能不正确。此外,还需要注意聚合操作的嵌套顺序,例如在使用SumAggregationBuilder时,需要将其添加到TermsAggregationBuilder中,否则聚合结果可能不正确。

索引或文档操作失败

解决方法:在进行索引或文档操作时,需要注意操作的顺序和参数设置。例如,在使用IndexRequest创建文档时,需要设置文档的ID和源数据,否则文档创建可能失败。此外,还需要注意索引或文档的权限设置,确保当前用户有足够的权限进行操作。

搜索结果排序不正确

解决方法:在使用SearchSourceBuilder进行搜索时,可以通过设置sort方法来指定搜索结果的排序方式。例如:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.sort(new FieldSortBuilder("timestamp").order(SortOrder.DESC));

搜索结果高亮显示不正确

解决方法:在使用SearchSourceBuilder进行搜索时,可以通过设置highlighter方法来指定搜索结果的高亮显示方式。例如:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("message");
highlightBuilder.preTags("<em>");
highlightBuilder.postTags("</em>");
sourceBuilder.highlighter(highlightBuilder);

以上代码中,我们使用HighlightBuilder指定按照message字段进行高亮显示,高亮标签为

连接池耗尽或内存溢出

解决方法:在使用RestHighLevelClient进行操作时,需要注意连接池和内存的使用。可以通过设置RestClientBuilder的setMaxConnTotal和setMaxConnPerRoute方法来控制连接池的大小,以及通过设置setHttpClientConfigCallback方法来控制内存的使用。例如:

RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
builder.setMaxConnTotal(100);
builder.setMaxConnPerRoute(50);
builder.setHttpClientConfigCallback(httpClientBuilder -> {
    httpClientBuilder.setMaxConnTotal(100);
    httpClientBuilder.setMaxConnPerRoute(50);
    return httpClientBuilder;
});
RestHighLevelClient client = new RestHighLevelClient(builder);

以上代码中,我们将连接池的大小设置为100,每个路由的最大连接数设置为50,并将HttpClient的最大连接数和每个路由的最大连接数也设置为50。这样可以避免连接池耗尽和内存溢出的问题。

多用户操作保证有序性

  • 使用版本控制

Elasticsearch中的每个文档都有一个版本号,可以使用版本控制来保证多用户操作的有序性。当多个用户同时对同一个文档进行操作时,只有版本号最大的操作才会生效,其他操作会被忽略。可以使用IndexRequest的version和versionType参数来控制文档的版本号和版本控制方式。例如:

IndexRequest request = new IndexRequest("my_index");
request.id("1");
request.source("field", "value");
request.version(1);
request.versionType(VersionType.EXTERNAL);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);

以上代码中,我们使用version参数指定文档的版本号为1,使用versionType参数指定版本控制方式为EXTERNAL,表示使用外部版本号控制。

  • 使用乐观锁
    除了使用版本控制外,还可以使用乐观锁来保证多用户操作的有序性。乐观锁是一种无阻塞的锁机制,它不会阻塞其他用户的操作,而是在操作完成后检查是否有其他用户对同一个文档进行了修改。如果有,则需要重新执行操作,直到操作成功为止。可以使用UpdateRequest的ifSeqNo和ifPrimaryTerm参数来实现乐观锁。例如:
UpdateRequest request = new UpdateRequest("my_index", "_doc", "1");
request.doc("field", "new_value");
request.ifSeqNo(1);
request.ifPrimaryTerm(1);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值