赞
踩
Elasticsearch是一款功能强大的全文搜索引擎,它使用Lucene搜索库进行底层索引和搜索。Elasticsearch提供了许多高级查询技巧,可以帮助用户更准确、更高效地查询数据。本教程将介绍Elasticsearch的高级查询技巧,并提供一些示例代码来说明它们的使用。
Elasticsearch支持布尔查询,包括AND、OR和NOT运算符。这使得用户可以使用多个条件来限制查询结果。
例如,以下查询将返回所有匹配“foo”和“bar”的文档:
- GET /_search
- {
- "query": {
- "bool": {
- "must": [
- { "match": { "content": "foo" }},
- { "match": { "content": "bar" }}
- ]
- }
- }
- }
此外,可以使用“should”查询来匹配任意一个条件。以下查询将返回匹配“foo”或“bar”的所有文档:
- GET /_search
- {
- "query": {
- "bool": {
- "should": [
- { "match": { "content": "foo" }},
- { "match": { "content": "bar" }}
- ]
- }
- }
- }
Elasticsearch支持范围查询,可以用于查询一个字段是否在指定范围内。范围查询有两种类型:数值范围和日期范围。
例如,以下查询将返回所有年龄在18到30岁之间的用户:
- GET /_search
- {
- "query": {
- "range": {
- "age": {
- "gte": 18,
- "lte": 30
- }
- }
- }
- }
以下查询将返回所有注册日期在2019年1月1日到2020年1月1日之间的用户:
- GET /_search
- {
- "query": {
- "range": {
- "registered_at": {
- "gte": "2019-01-01",
- "lte": "2020-01-01"
- }
- }
- }
- }
Elasticsearch支持模糊查询,可以用于查询包含拼写错误或近似匹配的文档。模糊查询使用模糊匹配算法(如编辑距离算法)来找到近似匹配的文档。
例如,以下查询将返回包含“fox”或“fix”的文档:
- GET /_search
- {
- "query": {
- "fuzzy": {
- "content": {
- "value": "fox",
- "fuzziness": "2"
- }
- }
- }
- }
“fuzziness”参数指定了允许的最大编辑距离。在上面的例子中,“fuzziness”为2,表示查询将匹配编辑距离为1或2的文档。
Elasticsearch支持正则表达式查询,可以用于查询符合指定模式的文本。正则表达式查询可以使用“regexp”查询类型。
例如,以下查询将返回包含“foo”或“bar”的文档:
- GET /_search
- {
- "query": {
- "regexp": {
- "content": "foo|bar"
- }
- }
- }
Elasticsearch支持通配符查询,可以用于查询包含通配符模式的文本。通配符查询可以使用“wildcard”查询类型。
例如,以下查询将返回包含以“foo”或“bar”开头的文档:
- GET /_search
- {
- "query": {
- "wildcard": {
- "content": "foo* OR bar*"
- }
- }
- }
Elasticsearch支持短语查询,可以用于查询包含一个或多个短语的文档。短语查询可以使用“match_phrase”查询类型。
例如,以下查询将返回包含短语“quick brown fox”或“lazy dog”的文档:
- GET /_search
- {
- "query": {
- "match_phrase": {
- "content": "quick brown fox lazy dog"
- }
- }
- }
Elasticsearch支持高亮显示查询结果中的关键字,可以用于使查询结果更易于理解。可以使用“highlight”参数来启用高亮显示。
例如,以下查询将返回包含“foo”或“bar”的文档,并将查询结果中的关键字高亮显示:
- GET /_search
- {
- "query": {
- "bool": {
- "should": [
- { "match": { "content": "foo" }},
- { "match": { "content": "bar" }}
- ]
- }
- },
- "highlight": {
- "fields": {
- "content": {}
- }
- }
- }

Elasticsearch支持分页和排序查询结果。可以使用“from”和“size”参数来指定返回结果的起始位置和数量。可以使用“sort”参数来指定排序方式。
例如,以下查询将返回从第10个文档开始的5个文档,并按照“age”字段进行升序排序:
- GET /_search
- {
- "from": 10,
- "size": 5,
- "query": {
- "match_all": {}
- },
- "sort": [
- { "age": "asc" }
- ]
- }
Elasticsearch支持聚合查询,可以用于对文档进行统计和分组。聚合查询可以使用“aggs”参数来启用。
例如,以下查询将返回“content”字段中包含每个单词的文档数量:
- GET /_search
- {
- "query": {
- "match_all": {}
- },
- "aggs": {
- "word_count": {
- "terms": {
- "field": "content"
- }
- }
- }
- }
以上就是Elasticsearch的一些高级查询技巧。下面将提供一些示例代码来说明它们的使用。
示例代码如下:
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
-
- 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.common.text.Text;
- import org.elasticsearch.index.query.MatchQueryBuilder;
- import org.elasticsearch.index.query.QueryBuilders;
- import org.elasticsearch.index.query.RangeQueryBuilder;
- import org.elasticsearch.search.SearchHit;
- import org.elasticsearch.search.SearchHits;
- import org.elasticsearch.search.builder.SearchSourceBuilder;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.Field;
-
- public class ElasticsearchDemo {
-
- public static void main(String[] args) throws IOException {
- // 创建客户端
- RestHighLevelClient client = new RestHighLevelClient(
- RestClient.builder(new HttpHost("localhost", 9200, "http")));
-
- // 创建索引和映射
- createIndexAndMapping(client);
-
- // 插入文档
- insertDocument(client);
-
- // 查询
- MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("content", "elasticsearch");
- SearchRequest searchRequest = new SearchRequest("my_index");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(matchQuery);
- searchRequest.source(searchSourceBuilder);
- SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
- printSearchResult(response);
-
- // 带有高亮显示的查询
- HighlightBuilder highlightBuilder = new HighlightBuilder();
- highlightBuilder.field(new Field("content").preTags("<em>").postTags("</em>"));
- searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(matchQuery);
- searchSourceBuilder.highlighter(highlightBuilder);
- searchRequest = new SearchRequest("my_index");
- searchRequest.source(searchSourceBuilder);
- response = client.search(searchRequest, RequestOptions.DEFAULT);
- printSearchResultWithHighlight(response);
-
- // 范围查询
- RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("publish_date")
- .from("2020-01-01")
- .to("2021-12-31");
- searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(rangeQuery);
- searchRequest = new SearchRequest("my_index");
- searchRequest.source(searchSourceBuilder);
- response = client.search(searchRequest, RequestOptions.DEFAULT);
- printSearchResult(response);
-
- // 排序
- searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(matchQuery);
- searchSourceBuilder.sort("publish_date");
- searchRequest = new SearchRequest("my_index");
- searchRequest.source(searchSourceBuilder);
- response = client.search(searchRequest, RequestOptions.DEFAULT);
- printSearchResult(response);
-
- // 删除索引
- deleteIndex(client);
-
- // 关闭客户端
- client.close();
- }
-
- private static void createIndexAndMapping(RestHighLevelClient client) throws IOException {
- // 创建索引
- Map<String, Object> settings = new HashMap<>();
- settings.put("number_of_shards", 1);
- settings.put("number_of_replicas", 0);
- Map<String, Object> mapping = new HashMap<>();
- Map<String, Object> properties = new HashMap<>();
- properties.put("title", Map.of("type", "text"));
- properties.put("content", Map.of("type", "text"));
- properties.put("publish_date", Map.of("type", "date"));
- mapping.put("properties", properties);
- client.indices().create(Map.of("index", "my_index", "settings", settings, "mapping", mapping),
- RequestOptions.DEFAULT);
- }
-
- private static void insertDocument(RestHighLevelClient client) throws IOException {
- // 插入文档
- Map<String, Object> document = new HashMap<>();
- document.put("title", "Elasticsearch Guide");
- document.put("content", "This is a guide to Elasticsearch.");
- document.put("publish_date", "2021-03-01");
- client.index(Map.of("index", "my_index", "id", "1", "body", document), RequestOptions.DEFAULT);
- }
-
- private static void deleteIndex(RestHighLevelClient client) throws IOException {
- // 删除索引
- client.indices().delete(Map.of("index", "my_index"), RequestOptions.DEFAULT);
- }
-
- private static void printSearchResult(SearchResponse response) {
- // 打印查询结果
- SearchHits hits = response.getHits();
- System.out.println("Total hits: " + hits.getTotalHits().value);
- System.out.println("Hits:");
- for (SearchHit hit : hits) {
- System.out.println("Id: " + hit.getId());
- System.out.println("Score: " + hit.getScore());
- System.out.println("Title: " + hit.getSourceAsMap().get("title"));
- System.out.println("Content: " + hit.getSourceAsMap().get("content"));
- System.out.println("Publish date: " + hit.getSourceAsMap().get("publish_date"));
- }
- }
-
- private static void printSearchResultWithHighlight(SearchResponse response) {
- // 打印带有高亮显示的查询结果
- SearchHits hits = response.getHits();
- System.out.println("Total hits: " + hits.getTotalHits().value);
- System.out.println("Hits:");
- for (SearchHit hit : hits) {
- System.out.println("Id: " + hit.getId());
- System.out.println("Score: " + hit.getScore());
- System.out.println("Title: " + hit.getSourceAsMap().get("title"));
- HighlightField highlightField = hit.getHighlightFields().get("content");
- if (highlightField != null) {
- Text[] fragments = highlightField.fragments();
- String content = "";
- for (Text fragment : fragments) {
- content += fragment;
- }
- System.out.println("Content: " + content);
- } else {
- System.out.println("Content: " + hit.getSourceAsMap().get("content"));
- }
- System.out.println("Publish date: " + hit.getSourceAsMap().get("publish_date"));
- }
- }
- }

这里我们使用了Elasticsearch高级REST客户端API来实现示例代码,相较于低级API,使用高级API的好处在于更易用,而且使用方式更加接近面向对象编程,提高了开发效率。
首先,我们需要添加相关依赖。在pom.xml
文件中添加以下依赖:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
- <dependency>
- <groupId>org.elasticsearch.client</groupId>
- <artifactId>elasticsearch-rest-high-level-client</artifactId>
- <version>7.15.2</version>
- </dependency>
其中,spring-boot-starter-data-elasticsearch
依赖为Spring Boot提供的与Elasticsearch集成的基础依赖,elasticsearch-rest-high-level-client
为Elasticsearch高级REST客户端API的依赖。
接下来,我们创建一个Spring Boot主类,并在其中添加如下代码:
- import org.elasticsearch.action.delete.DeleteRequest;
- import org.elasticsearch.action.index.IndexRequest;
- import org.elasticsearch.action.search.SearchRequest;
- import org.elasticsearch.action.search.SearchResponse;
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.common.settings.Settings;
- import org.elasticsearch.common.unit.TimeValue;
- import org.elasticsearch.index.query.BoolQueryBuilder;
- import org.elasticsearch.index.query.QueryBuilders;
- import org.elasticsearch.search.SearchHit;
- import org.elasticsearch.search.builder.SearchSourceBuilder;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.Field;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.HighlightQuery;
- import org.elasticsearch.search.sort.SortOrder;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- import org.springframework.data.elasticsearch.client.RestClients;
-
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
-
- @SpringBootApplication
- public class ElasticsearchDemoApplication implements CommandLineRunner {
-
- public static void main(String[] args) {
- SpringApplication.run(ElasticsearchDemoApplication.class, args);
- }
-
- @Bean
- public RestHighLevelClient client() {
- return RestClients.create(RestClients.createLocalHost()).rest();
- }
-
- @Override
- public void run(String... args) throws Exception {
- RestHighLevelClient client = client();
- try {
- createIndex(client);
- insertDocument(client);
- searchDocument(client);
- deleteIndex(client);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- client.close();
- }
- }
-
- private static void createIndex(RestHighLevelClient client) throws IOException {
- // 创建索引
- Settings.Builder settings = Settings.builder()
- .put("index.number_of_shards", 1)
- .put("index.number_of_replicas", 0);
- Map<String, Object> mapping = new HashMap<>();
- Map<String, Object> properties = new HashMap<>();
- properties.put("title", Map.of("type", "text"));
- properties.put("content", Map.of("type", "text"));
- properties.put("publish_date", Map.of("type", "date"));
- mapping.put("properties", properties);
- client.indices().create(Map.of("index", "my_index", "settings", settings, "mapping", mapping),
- RequestOptions.DEFAULT);
- }
-
- private static void insertDocument(RestHighLevelClient client) throws IOException {
- // 插入文档
- Map<String, Object> document = new HashMap<>();
- document.put("title", "Elasticsearch Guide");
- document.put("content", "This is a guide to
- IndexRequest request = new IndexRequest("my_index")
- .id("1")
- .source(document);
- client.index(request, RequestOptions.DEFAULT);
- }
- private static void searchDocument(RestHighLevelClient client) throws IOException {
- // 搜索文档
- SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
- BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
- .must(QueryBuilders.matchQuery("title", "Elasticsearch"))
- .should(QueryBuilders.matchQuery("content", "guide"));
- sourceBuilder.query(boolQueryBuilder)
- .sort("publish_date", SortOrder.DESC)
- .from(0)
- .size(10)
- .timeout(TimeValue.timeValueSeconds(1))
- .fetchSource(new String[]{"title", "publish_date"}, new String[]{"content"});
- HighlightBuilder highlightBuilder = new HighlightBuilder()
- .field(new Field("title"))
- .highlightQuery(new HighlightQuery().matchQuery(new HashMap<String, Object>() {{
- put("title", new HashMap<>());
- }}));
- sourceBuilder.highlighter(highlightBuilder);
- SearchRequest request = new SearchRequest("my_index").source(sourceBuilder);
- SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- System.out.println("Total hits: " + response.getHits().getTotalHits().value);
- for (SearchHit hit : response.getHits().getHits()) {
- System.out.println("Title: " + hit.getSourceAsMap().get("title"));
- System.out.println("Publish date: " + hit.getSourceAsMap().get("publish_date"));
- System.out.println("Content: " + hit.getHighlightFields().get("title").fragments()[0].string());
- System.out.println("--------------------------");
- }
- }
- private static void deleteIndex(RestHighLevelClient client) throws IOException {
- // 删除索引
- DeleteRequest request = new DeleteRequest("my_index");
- client.indices().delete(request, RequestOptions.DEFAULT);
- }
- }

我们在主类ElasticsearchDemoApplication
中实现了CommandLineRunner
接口,以便在应用启动时执行相关方法。在run
方法中,我们调用了创建索引、插入文档、搜索文档和删除索引的方法。这些方法的具体实现与示例代码中的实现相同。
接下来,我们可以运行应用程序并查看结果。在终端中输入以下命令:
mvn spring-boot:run
通过这个Spring Boot实现,我们可以更方便地与Elasticsearch进行交互,而不必手动设置连接和释放资源等操作。此外,Spring Boot还提供了许多其他特性,例如自动配置和依赖注入等。这使得我们可以更加专注于业务逻辑,而不必过多关注与Elasticsearch的交互。
Elasticsearch是一个功能强大的搜索引擎,拥有许多高级查询技巧。在实际使用中,可以根据具体需求选择合适的查询方式,并使用查询语句中的高级功能,来实现更复杂的查询操作。本教程介绍了Elasticsearch的基本查询方式和高级查询技巧,并提供了相应的代码示例,希望能帮助读者更好地掌握Elasticsearch的查询功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。