【Elasticsearch】搜索类型介绍,以及使用SpringBoot实现,并展现给前端

server/2025/1/17 19:16:28/

Elasticsearch 提供了多种查询类型,每种查询类型适用于不同的搜索场景。以下是八种常见的 Elasticsearch 查询类型及其详细说明和示例。

1. Match Query

用途:用于全文搜索,会对输入的文本进行分词,并在索引中的字段中查找这些分词。 特点:支持模糊匹配、短语匹配等。

示例

json

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

2. Term Query

用途:用于精确匹配,不会对输入的文本进行分词。 特点:适用于关键词、ID 等不需要分词的情况。

示例

json

GET /my_index/_search
{"query": {"term": {"status": "active"}}
}

3. Terms Query

用途:用于在一个字段上匹配多个值。 特点:类似于 SQL 中的 IN 操作符。

示例

json

GET /my_index/_search
{"query": {"terms": {"tags": ["news", "sports"]}}
}

4. Range Query

用途:用于范围查询,可以指定数值或日期范围。 特点:适用于数值型字段和日期字段。

示例

json

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

5. Bool Query

用途:组合多个查询条件,支持 must(必须满足)、should(应该满足)、must_not(必须不满足)和 filter(过滤)子句。 特点:灵活性高,可以构建复杂的查询逻辑。

示例

json

GET /my_index/_search
{"query": {"bool": {"must": [{ "match": { "title": "Elasticsearch" } },{ "range": { "date": { "gte": "now-1y/d" }}}],"filter": [{ "term": { "status": "published" }}]}}
}

6. Wildcard Query

用途:使用通配符进行匹配。 特点:支持 *? 通配符,但性能较差,应谨慎使用。

示例

json

GET /my_index/_search
{"query": {"wildcard": {"name": "joh*"}}
}

7. Fuzzy Query

用途:用于近似匹配,允许一定数量的拼写错误。 特点:适用于拼写错误较多的搜索场景。

示例
GET /my_index/_search
{"query": {"fuzzy": {"username": {"value": "kenneth","fuzziness": "AUTO"}}}
}

8. Match Phrase Query

用途:用于精确匹配整个短语。 特点:不会对短语进行分词,要求短语完全一致。

示例

json

GET /my_index/_search
{"query": {"match_phrase": {"description": "Elasticsearch search engine"}}
}

总结

每种查询类型都有其特定的应用场景和优缺点:

  • Match Query:适合全文搜索。
  • Term Query:适合精确匹配。
  • Terms Query:适合多值匹配。
  • Range Query:适合范围查询。
  • Bool Query:适合复杂查询逻辑。
  • Wildcard Query:适合通配符匹配,性能较低。
  • Fuzzy Query:适合拼写错误匹配。
  • Match Phrase Query:适合精确短语匹配。

通过合理选择和组合这些查询类型,可以实现高效且灵活的搜索功能。

参考资料

  • Elasticsearch 官方文档
  • Elasticsearch 查询 DSL 指南

这些资源提供了更多关于 Elasticsearch 查询类型的详细信息和示例,帮助你更好地理解和使用这些查询

为了实现八种 Elasticsearch 查询类型并在 Web 前端展示结果,我们可以使用 Spring Boot 构建后端服务,并使用 Thymeleaf 作为模板引擎来构建前端页面。以下是一个完整的示例,展示如何实现这八种查询类型并将结果显示在 Web 前端。

项目结构

spring-boot-elasticsearch-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── controller/
│   │   │           │   └── SearchController.java
│   │   │           ├── model/
│   │   │           │   └── Document.java
│   │   │           ├── repository/
│   │   │           │   └── DocumentRepository.java
│   │   │           ├── service/
│   │   │           │   └── SearchService.java
│   │   │           └── SpringBootElasticsearchDemoApplication.java
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── static/
│   │       └── templates/
│   │           └── search.html
├── pom.xml

1. 添加依赖

pom.xml 中添加必要的依赖:

xml

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.6.2</version></dependency>
</dependencies>

2. 配置文件

src/main/resources/application.yml 中配置 Elasticsearch 连接信息:

yaml

spring:elasticsearch:rest:uris: http://localhost:9200server:port: 8080

3. 实体类

创建一个实体类 Document.java 表示索引中的文档:

java

package com.example.model;import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;@Data
@Document(indexName = "documents")
public class Document {@Idprivate String id;@Field(type = FieldType.Text)private String title;@Field(type = FieldType.Text)private String content;@Field(type = FieldType.Integer)private Integer age;@Field(type = FieldType.Date)private String date;@Field(type = FieldType.Keyword)private String status;@Field(type = FieldType.Keyword)private String[] tags;@Field(type = FieldType.Keyword)private String username;
}

4. Repository 接口

创建一个 Repository 接口 DocumentRepository.java

java

package com.example.repository;import com.example.model.Document;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;public interface DocumentRepository extends ElasticsearchRepository<Document, String> {
}

5. Service 层

创建一个 Service 类 SearchService.java 来处理各种查询逻辑:

java

package com.example.service;import com.example.model.Document;
import com.example.repository.DocumentRepository;
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.index.query.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Service
public class SearchService {@Autowiredprivate RestHighLevelClient client;public List<Document> matchQuery(String field, String query) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(field, query);sourceBuilder.query(matchQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> termQuery(String field, String value) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(field, value);sourceBuilder.query(termQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> termsQuery(String field, List<String> values) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(field, values);sourceBuilder.query(termsQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> rangeQuery(String field, Object gte, Object lte) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(field).gte(gte).lte(lte);sourceBuilder.query(rangeQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> boolQuery(Map<String, Object> mustQueries, Map<String, Object> shouldQueries, Map<String, Object> mustNotQueries) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();if (mustQueries != null) {for (Map.Entry<String, Object> entry : mustQueries.entrySet()) {boolQueryBuilder.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));}}if (shouldQueries != null) {for (Map.Entry<String, Object> entry : shouldQueries.entrySet()) {boolQueryBuilder.should(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));}}if (mustNotQueries != null) {for (Map.Entry<String, Object> entry : mustNotQueries.entrySet()) {boolQueryBuilder.mustNot(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));}}sourceBuilder.query(boolQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> wildcardQuery(String field, String value) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(field, value);sourceBuilder.query(wildcardQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> fuzzyQuery(String field, String value) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery(field, value);sourceBuilder.query(fuzzyQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}public List<Document> matchPhraseQuery(String field, String phrase) throws IOException {SearchRequest searchRequest = new SearchRequest("documents");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery(field, phrase);sourceBuilder.query(matchPhraseQueryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);return getDocumentsFromResponse(searchResponse);}private List<Document> getDocumentsFromResponse(SearchResponse searchResponse) {List<Document> documents = new ArrayList<>();searchResponse.getHits().forEach(hit -> {Document document = new Document();document.setId(hit.getId());document.setTitle((String) hit.getSourceAsMap().get("title"));document.setContent((String) hit.getSourceAsMap().get("content"));document.setAge((Integer) hit.getSourceAsMap().get("age"));document.setDate((String) hit.getSourceAsMap().get("date"));document.setStatus((String) hit.getSourceAsMap().get("status"));document.setTags((String[]) hit.getSourceAsMap().get("tags"));document.setUsername((String) hit.getSourceAsMap().get("username"));documents.add(document);});return documents;}
}

6. Controller 层

创建一个 Controller 类 SearchController.java 来处理 HTTP 请求并返回结果:

java

package com.example.controller;import com.example.model.Document;
import com.example.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Controller
public class SearchController {@Autowiredprivate SearchService searchService;@GetMapping("/search")public String search(@RequestParam(required = false) String queryType,@RequestParam(required = false) String field,@RequestParam(required = false) String query,@RequestParam(required = false) String value,@RequestParam(required = false) String gte,@RequestParam(required = false) String lte,@RequestParam(required = false) String[] values,Model model) throws IOException {List<Document> results = null;switch (queryType) {case "match":results = searchService.matchQuery(field, query);break;case "term":results = searchService.termQuery(field, value);break;case "terms":results = searchService.termsQuery(field, List.of(values));break;case "range":results = searchService.rangeQuery(field, gte, lte);break;case "bool":Map<String, Object> mustQueries = new HashMap<>();Map<String, Object> shouldQueries = new HashMap<>();Map<String, Object> mustNotQueries = new HashMap<>();if (field != null && query != null) {mustQueries.put(field, query);}results = searchService.boolQuery(mustQueries, shouldQueries, mustNotQueries);break;case "wildcard":results = searchService.wildcardQuery(field, value);break;case "fuzzy":results = searchService.fuzzyQuery(field, value);break;case "match_phrase":results = searchService.matchPhraseQuery(field, query);break;default:// Handle default case or throw an exceptionbreak;}model.addAttribute("results", results);return "search";}
}

7. 前端页面

创建一个 Thymeleaf 模板 search.html 来展示搜索结果:

html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Elasticsearch Queries</title><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5"><h1>Elasticsearch Queries</h1><form method="get" action="/search"><div class="form-group"><label for="queryType">Query Type:</label><select class="form-control" id="queryType" name="queryType"><option value="match">Match</option><option value="term">Term</option><option value="terms">Terms</option><option value="range">Range</option><option value="bool">Bool</option><option value="wildcard">Wildcard</option><option value="fuzzy">Fuzzy</option><option value="match_phrase">Match Phrase</option></select></div><div class="form-group"><label for="field">Field:</label><input type="text" class="form-control" id="field" name="field"></div><div class="form-group"><label for="query">Query:</label><input type="text" class="form-control" id="query" name="query"></div><div class="form-group"><label for="value">Value:</label><input type="text" class="form-control" id="value" name="value"></div><div class="form-group"><label for="gte">GTE:</label><input type="text" class="form-control" id="gte" name="gte"></div><div class="form-group"><label for="lte">LTE:</label><input type="text" class="form-control" id="lte" name="lte"></div><div class="form-group"><label for="values">Values (comma separated):</label><input type="text" class="form-control" id="values" name="values"></div><button type="submit" class="btn btn-primary">Search</button></form><hr><h2>Results:</h2><table class="table table-striped"><thead><tr><th>ID</th><th>Title</th><th>Content</th><th>Age</th><th>Date</th><th>Status</th><th>Tags</th><th>Username</th></tr></thead><tbody><tr th:each="document : ${results}"><td th:text="${document.id}"></td><td th:text="${document.title}"></td><td th:text="${document.content}"></td><td th:text="${document.age}"></td><td th:text="${document.date}"></td><td th:text="${document.status}"></td><td th:text="${#strings.arrayJoin(document.tags, ', ')}"></td><td th:text="${document.username}"></td></tr></tbody></table>
</div>
</body>
</html>

8. 启动类

创建启动类 SpringBootElasticsearchDemoApplication.java

java

package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootElasticsearchDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringBootElasticsearchDemoApplication.class, args);}
}

9. 测试数据

确保 Elasticsearch 中有一些测试数据以便进行查询。你可以使用 Kibana 或 curl 命令插入一些文档到 documents 索引中。

示例文档

json

POST /documents/_doc/1
{"title": "Introduction to Elasticsearch","content": "Elasticsearch is a distributed, RESTful search and analytics engine.","age": 5,"date": "2023-01-01","status": "published","tags": ["elasticsearch", "search"],"username": "john_doe"
}POST /documents/_doc/2
{"title": "Advanced Elasticsearch Techniques","content": "Learn advanced techniques in Elasticsearch for better performance.","age": 3,"date": "2023-06-15","status": "draft","tags": ["elasticsearch", "advanced"],"username": "jane_smith"
}

10. 运行项目

  1. 启动 Elasticsearch:确保 Elasticsearch 服务器正在运行。
  2. 插入测试数据:使用上述示例文档插入测试数据。
  3. 启动 Spring Boot 应用

bash

./mvnw spring-boot:run

4.访问应用:打开浏览器,访问 http://localhost:8080/search

使用说明

在前端页面中,可以选择不同的查询类型并输入相应的参数,点击“Search”按钮即可查看查询结果。以下是每种查询类型的示例参数:

  • Match Query

    • Query Type: match
    • Field: content
    • Query: introduction
  • Term Query

    • Query Type: term
    • Field: status
    • Value: published
  • Terms Query

  • Range Query

    • Query Type: range
    • Field: age
    • GTE: 1
    • LTE: 5
  • Bool Query

    • Query Type: bool
    • Field: status
    • Query: published
  • Wildcard Query

    • Query Type: wildcard
    • Field: username
    • Value: john*
  • Fuzzy Query

    • Query Type: fuzzy
    • Field: username
    • Value: jon_doe
  • Match Phrase Query

    • Query Type: match_phrase
    • Field: title
    • Query: Introduction to Elasticsearch

通过这种方式,你可以在 Web 前端展示和测试八种常见的 Elasticsearch 查询类型。


http://www.ppmy.cn/server/159164.html

相关文章

《零基础Go语言算法实战》【题目 2-25】goroutine 的执行权问题

《零基础Go语言算法实战》 【题目 2-25】goroutine 的执行权问题 请说明以下这段代码为什么会卡死。 package main import ( "fmt" "runtime" ) func main() { var i byte go func() { for i 0; i < 255; i { } }() fmt.Println("start&quo…

《leetcode-runner》如何手搓一个debug调试器——引言

文章目录 背景 仓库地址&#xff1a;leetcode-runner 背景 最近笔者写了个idea插件——leetcode-runner。该插件可以让扣友在本地刷leetcode&#xff0c;并且leetcode提供的和代码相关的编辑功能该插件都提供&#xff0c;具体演示如下 唯一不足的就是代码debug。众所周知&…

OpenCV相机标定与3D重建(59)用于立体相机标定的函数stereoCalibrate()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 标定立体相机设置。此函数找到两个相机各自的内参以及两个相机之间的外参。 cv::stereoCalibrate 是 OpenCV 中用于立体相机标定的函数。它通过一…

Python----Python爬虫(Scrapy的应用:CrawlSpider 使用,爬取小说,CrawlSpider版)

一、CrawlSpider 使用 1.1、CrawlSpider CrawSpiders 是 Scrapy 框架中的一个特殊爬虫类&#xff0c;它用于处理需要跟随链接并抓取多个页面的情况。相比于基本的 Spider 类&#xff0c;CrawSpiders 提供了一个更灵活、更强大的方式来定义爬取规则。 在Scrapy中Spider是所有爬…

[Effective C++]条款47 萃取器

本文初发于 “天目中云的小站”&#xff0c;同步转载于此。 条款47 : 请使用traits classes表现类型信息 traits classes(萃取器类), 如你所见萃取器其实是一个模板类, 在C中萃取器是一个神奇且有趣的存在, 它被广泛引用于标准库STL的编写中, 我们将在本条款中了解萃取器的功能…

设计模式-工厂模式/抽象工厂模式

工厂模式 定义 定义一个创建对象的接口&#xff0c;让子类决定实列化哪一个类&#xff0c;工厂模式使一个类的实例化延迟到其子类&#xff1b; 工厂方法模式是简单工厂模式的延伸。在工厂方法模式中&#xff0c;核心工厂类不在负责产品的创建&#xff0c;而是将具体的创建工作…

深入理解JavaScript闭包:原理、实践和优化

引言 在JavaScript中&#xff0c;闭包是一个非常重要的概念。它允许函数访问其外部作用域中的变量&#xff0c;即使这些变量在其定义的作用域之外。闭包的出现使得JavaScript能够实现许多高级功能&#xff0c;如模块封装、事件处理、异步编程等。然而&#xff0c;闭包的使用也…

长安“战疫”网络安全公益赛的一些随想

起因 今年刚进入大学&#xff0c;开始带校队&#xff0c;为了培养校队新成员&#xff0c;也就一直计划着和当地的一些高校合作交流&#xff0c;但是由于种种原因一直被搁置下来。正巧学校信息中心和四叶草有一个培训项目的合作&#xff0c;学校的网安协会也算是沾了光成为了培…