ES概述

ES (Elasticsearch) 是一个分布式的搜索和分析引擎,它支持使用一种类似于 SQL 的查询语法,称为 Elasticsearch 查询语法。以下是 Elasticsearch 查询语法的基本概念和语法结构:

  1. 索引 (Index):Elasticsearch 中的数据存储在索引中,一个索引包含多个文档,每个文档都有一个唯一的 ID。

  2. 类型 (Type):索引可以包含多个类型,每个类型定义了一组字段。

  3. 字段 (Field):类型中的每个字段都有一个名称和类型,可以包含单个值或多个值。

  4. 映射 (Mapping):定义了文档如何被存储和索引的方式。

  5. 查询 (Query):用于搜索索引中的文档,可以使用各种查询类型,如全文搜索、精确匹配、范围查询等。

常用ES语法

以下是一些常用的 Elasticsearch 查询语法示例:

匹配查询 (Match Query): 用于执行全文搜索,可以通过指定要搜索的字段和要搜索的文本来进行搜索。

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": "quick brown fox"
    }
  }
}

多字段匹配查询 (Multi-match Query): 与匹配查询类似,但可以在多个字段中搜索。

GET /my_index/my_type/_search
{
  "query": {
    "multi_match": {
      "query": "quick brown fox",
      "fields": ["title", "content"]
    }
  }
}

范围查询 (Range Query): 用于搜索一个范围内的值。


GET /my_index/my_type/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 18,
        "lte": 30
      }
    }
  }
}

布尔查询 (Boolean Query): 用于组合多个查询,可以使用 AND、OR、NOT 运算符组合查询


GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "quick" }},
        { "match": { "title": "brown" }}
      ],
      "must_not": [
        { "match": { "title": "dog" }}
      ]
    }
  }
}

模糊查询 (Fuzzy Query): 用于搜索与给定文本相似的文档,可以在一定程度上处理拼写错误。


GET /my_index/my_type/_search
{
  "query": {
    "fuzzy": {
      "title": {
        "value": "fox",
        "fuzziness": "2"
      }
    }
  }
}

前缀查询 (Prefix Query): 用于搜索以指定前缀开头的文档。


GET /my_index/my_type/_search
{
  "query": {
    "prefix": {
      "title": "qu"
    }
  }
}

正则表达式查询 (Regexp Query): 用于搜索与指定正则表达式匹配的文档。


GET /my_index/my_type/_search
{
  "query": {
    "regexp": {
      "title": "q[a-z]*k"
    }
  }
}

短语查询 (Phrase Query): 用于搜索包含指定短语的文档。


GET /my_index/my_type/_search
{
  "query": {
    "match_phrase": {
      "title": "quick brown"
    }
  }
}

聚合查询 (Aggregation Query): 用于对搜索结果进行分组和计算统计信息,例如求平均值、最大值、最小值等


GET /my_index/my_type/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "avg_age": {
      "avg": {
        "field": "age"
      }
    }
  }
}

Java ES示例

Java API 连接 Elasticsearch 并进行搜索的简单示例:

import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.TimeValue;

import java.io.IOException;

public class ElasticsearchExample {
    private static final String INDEX_NAME = "my_index";
    private static final String TYPE_NAME = "my_type";
    private static final String HOST_NAME = "localhost";
    private static final int PORT_NUMBER = 9200;

    public static void main(String[] args) {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(HOST_NAME, PORT_NUMBER));

        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        searchRequest.types(TYPE_NAME);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("title", "quick brown"));
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(10);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        searchRequest.source(searchSourceBuilder);

        try {
            SearchResponse searchResponse = client.search(searchRequest);
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                System.out.println(hit.getSourceAsString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

此示例首先创建了一个 RestHighLevelClient 对象,该对象将用于连接 Elasticsearch。然后,创建一个 SearchRequest 对象,该对象指定要搜索的索引和类型,并设置搜索条件。接下来,使用 SearchSourceBuilder 对象指定搜索条件的详细信息,如匹配查询、分页和超时时间等。最后,调用 client.search() 方法执行搜索并处理结果。

请注意,此示例中使用的 Elasticsearch 版本是 6.x,如果您使用的是不同的版本,则需要相应地调整代码。另外,为了简化示例,没有包含异常处理和资源管理代码,实际上需要根据具体情况进行处理。

常用ES方法

以下是一些 Java API 中常用的 Elasticsearch 方法:

连接 Elasticsearch 集群:

RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(new HttpHost("localhost", 9200, "http")));

索引文档:


IndexRequest request = new IndexRequest("my_index", "my_type", "1");
String jsonString = "{" +
        "\"title\":\"example title\"," +
        "\"content\":\"example content\"" +
        "}";
request.source(jsonString, XContentType.JSON);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);

更新文档:


UpdateRequest request = new UpdateRequest("my_index", "my_type", "1");
String jsonString = "{" +
        "\"title\":\"updated title\"" +
        "}";
request.doc(jsonString, XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);

获取文档:


GetRequest request = new GetRequest("my_index", "my_type", "1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);

删除文档:

DeleteRequest request = new DeleteRequest("my_index", "my_type", "1");
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);

执行搜索:


SearchRequest request = new SearchRequest("my_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("title", "example"));
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);

创建索引:


CreateIndexRequest request = new CreateIndexRequest("my_index");
request.settings(Settings.builder()
        .put("index.number_of_shards", 1)
        .put("index.number_of_replicas", 2));
request.mapping("my_type", "title", "type=text");
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);

删除索引:


DeleteIndexRequest request = new DeleteIndexRequest("my_index");
AcknowledgeResponse response = client.indices().delete(request, RequestOptions.DEFAULT);

使用ES常用优化建议

使用 Java API 连接 Elasticsearch 时查询优化的一些建议:

  1. 使用合适的查询类型:Elasticsearch 支持多种查询类型,包括精确匹配、模糊匹配、范围查询、全文搜索等。根据查询的需求选择最合适的查询类型可以提高查询效率。

  2. 使用查询语法:使用查询语法可以更精确地指定查询条件和过滤条件,避免在结果中返回不必要的数据。Elasticsearch 查询语法包括布尔查询、范围查询、通配符查询、正则表达式查询、前缀查询、短语查询等。

  3. 使用索引优化:合理设计索引结构可以显著提高查询效率。例如,为高频查询的字段创建索引、避免创建大量冗余字段、使用合适的分词器等。

  4. 缓存查询结果:如果某个查询经常被使用,并且查询结果比较稳定,可以考虑将查询结果缓存起来。这可以减少查询次数和查询时间,提高查询效率。

  5. 批量查询:将多个查询合并为一个批量查询可以减少网络传输时间和资源消耗。使用批量查询可以将多个查询一起发送给 Elasticsearch,并在一次请求中获取多个结果。

  6. 使用聚合:使用聚合可以对查询结果进行分组、统计、排序等操作。聚合操作通常比单独的查询更加高效,因为它可以在 Elasticsearch 内部进行操作,而不需要在客户端进行处理。

  7. 避免过多数据:当查询结果集非常大时,应该考虑限制返回的结果数量,或者使用滚动查询等技术进行分批处理。这可以避免在客户端处理过多的数据,导致内存溢出或性能下降。

总之,优化查询可以显著提高 Elasticsearch 查询的性能和效率。使用合适的查询类型、查询语法、索引优化、缓存查询结果、批量查询、聚合等技术可以帮助我们提高查询效率,减少资源消耗,同时提高系统的可靠性和稳定性。

使用ES注意事项

使用 Java API 连接 Elasticsearch 时需要注意的一些事项:

  1. 版本兼容性:确保使用的 Java API 版本与 Elasticsearch 版本兼容。建议使用最新版本的 Java API 和 Elasticsearch,以获得最佳性能和功能。

  2. 资源管理:确保在使用完资源后正确地关闭它们,例如关闭连接、释放内存等。不正确的资源管理可能会导致内存泄漏或连接池耗尽等问题。

  3. 错误处理:当使用 Java API 与 Elasticsearch 通信时,可能会出现各种类型的错误,例如网络故障、索引不存在等。确保在代码中包含适当的错误处理,以便在出现问题时进行恰当的处理。

  4. 查询优化:优化查询可以提高搜索性能和减少资源消耗。建议使用合适的查询类型、正确的查询语法和索引结构,以最大程度地提高搜索效率。

  5. 安全性:确保在连接 Elasticsearch 集群时使用适当的安全设置,例如身份验证、TLS/SSL 加密等。这有助于保护数据和防止未经授权的访问。

  6. 性能测试:在生产环境之前,建议进行性能测试以确保系统能够处理预期的负载并满足性能要求。可以使用诸如 JMeter 等性能测试工具对 Elasticsearch 进行负载测试。

总的来说,使用 Java API 连接 Elasticsearch 需要谨慎处理,确保代码正确性、资源管理、错误处理、查询优化、安全性和性能测试等方面都得到妥善处理。