| 特性 | Low-Level REST Client | High-Level REST Client | Java API Client |
|---|---|---|---|
| 抽象层级 | 最低,直接发送JSON请求 | 中,提供对象化的API | 最高,完全基于对象,类型安全 |
| 官方状态 | 仍可用,但建议迁移 | 已弃用 (Deprecated),不再推荐 | 官方推荐 (Recommended) |
| 适用版本 | 所有版本 | ES 7.x 及更早版本 | ES 8.x 及以后版本 |
| 上手难度 | 较难,需手动构建JSON | 简单,API直观 | 中等,需理解新的函数式构建方式 |
黑马旅游案例:
yfeif/hotel-demo: 黑马旅游网案例
https://github.com/yfeif/hotel-demo
1.索引库操作

2.文档操作
文档操作根据原请求也能正常处理数据,但是有些解析的时候由于ES版本是8.4.1,依赖是7.12.1导致空指针异常,所以改写为初级的请求。

3.DSL 查询文档
1.DSL 查询分类
🔍 搜索引擎DSL查询的分类(以Elasticsearch/OpenSearch为例)
在搜索领域,DSL查询特指用JSON风格定义的查询语言。其查询可按结构 和功能进行分类,最常见的分类方式如下:
一、按查询结构分类
这是最基础的分类方式,将查询分为两大类:
| 类别 | 描述 | 特点 | 常见类型 |
|---|---|---|---|
| 叶子查询 (Leaf Query) | 在单个字段上查找特定值的查询,是查询的最小单元。 | 独立使用,针对特定字段执行搜索。 | 全文检索、精确查询、地理查询等。 |
| 复合查询 (Compound Query) | 包装一个或多个叶子查询或复合查询,用于组合条件或改变其行为。 | 通过逻辑运算(如布尔)组合多个查询条件。 | bool, function_score, dis_max 等。 |
二、按查询功能分类
在叶子查询内部,根据功能又可以细分为以下几种:
-
查询所有 :最简单,用于测试,返回索引中的所有文档。例如:
match_all。 -
全文检索查询 :对输入文本分词 后,在
text类型字段中搜索。例如:match(单字段)、multi_match(多字段)。 -
精确查询 :对
keyword、数值、日期等字段进行不分词 的精确查找。例如:term(精确值)、range(范围查询)。 -
地理查询 :基于经纬度等地理数据进行搜索。例如:
geo_distance(距离)、geo_bounding_box(矩形范围)。 -
专业查询 :处理特定需求的查询,如
span query(跨度查询,用于精确位置搜索)、nested query(嵌套查询)、joining query(关联查询)等。
📝 其他分类维度
-
查询 (Query) vs 过滤 (Filter) :
query上下文会计算相关性得分 并排序;filter上下文只做筛选,不计算得分,性能更高,常用于缓存。 -
按数据类型 :查询方式需匹配字段类型,例如
text字段用全文检索,keyword字段用精确查询。
💎 总结
简单来说,对DSL查询的分类可以从三个层面理解:
-
广义概念 :分为外部DSL 和内部DSL。
-
结构上 :分为叶子查询 和复合查询。
-
功能上 :叶子查询可进一步分为全文检索 、精确查询 、地理查询等。

html
# 查询所有
GET /hotel/_search
{
"query": {
"match_all": {}
}
}

2.全文检索查询
全文检索(Full-Text Search)是搜索引擎和数据库中最核心的查询方式之一,它不是为了进行简单的"字符串匹配",而是为了进行理解内容含义的"语义"搜索。
💡 什么是全文检索?
简单来说,全文检索的过程就像查字典:
-
建立索引(查字典前的准备工作):系统会像编写字典的"索引页"一样,扫描文档中的每一个词,为它们建立索引。这个索引会记录每个词出现在哪些文档、以及出现的次数和位置。这个索引结构通常被称为"倒排索引"(Inverted Index)。
-
执行搜索(根据索引查内容):当你输入关键词查询时,系统不会去原文里逐字扫描,而是直接去"倒排索引"这个目录里快速查找,然后返回包含这些词的文档。
这种"先建目录,再查目录"的方式,让检索效率远高于传统的LIKE模糊匹配。
⚙️ 核心原理:分词与倒排索引
全文检索之所以能"理解"你的搜索,主要依赖两个关键技术:
-
分词(Analysis) :在建立索引和执行搜索时,系统都会用分词器(Analyzer) 将文本切分成一个个独立的词条(Term)。例如,"我爱北京天安门"会被切分为"我"、"爱"、"北京"、"天安门"等词条。
-
倒排索引(Inverted Index):这是全文检索速度的保证。它是一个词条到文档ID的映射表,能快速定位包含特定词条的所有文档。
📋 常见查询类型(以Elasticsearch为例)
在实际使用中,最常见的全文检索查询类型如下:
| 查询类型 | 描述 | 适用场景 |
|---|---|---|
match 查询 |
最基础、最核心 的全文查询。会对输入进行分词,然后搜索任意一个分词结果。 | 绝大多数常规的搜索场景,如电商、博客的搜索框。 |
match_phrase 查询 |
短语匹配 。不仅要求所有词出现,还要求它们的顺序和位置必须一致。 | 搜索精确的短语,如"机器学习"、"中华人民共和国"。 |
multi_match 查询 |
match查询的多字段版本。可以在多个字段(如标题、内容、标签)中同时搜索。 |
不确定关键词在哪个字段,需要在多个字段中综合搜索。 |
query_string 查询 |
支持复杂的语法 ,如布尔逻辑(AND、OR、NOT)、通配符等。 |
提供给有经验的高级用户,进行精确、复杂的搜索。 |
simple_query_string 查询 |
query_string的简化、更健壮版本。对语法错误容忍度更高,更适合面向普通用户。 |
直接暴露给终端用户的搜索框,避免因用户输入特殊字符导致报错。 |
intervals 查询 |
高级匹配 。可以对匹配词项的顺序和邻近度(Proximity)进行精细控制。 | 法律、学术等对文本位置关系有严格要求的专业搜索。 |
此外,还有一些特定场景的变种,如match_phrase_prefix常用于搜索框的自动补全(Auto-complete)功能。
💎 总结:全文检索 vs. 精确查询
理解全文检索,关键在于区分它和精确查询(Term Query):
-
处理方式 :全文检索会对输入文本进行分词 ;而精确查询不会,它将输入作为一个整体。
-
搜索目标 :全文检索搜索的是分词后的词条 ;精确查询搜索的是未经处理的完整词条。
-
主要用途 :全文检索用于相关性搜索 ,如Google、百度;精确查询用于过滤,如查找特定ID、状态、精确分类等。
html
# match查询
GET /hotel/_search
{
"query": {
"match": {
"all": "外滩如家"
}
}
}
# multi_match查询
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "外滩如家",
"fields": ["brand","name","business"]
}
}

3.精准查询
在Elasticsearch等搜索引擎的DSL中,精确查询对应的是术语级查询(Term-level Query) 。它的核心特点是:查询条件不会被分词器处理,而是作为一个完整的、精确的词条(Term),直接去倒排索引中匹配。
简单来说,全文检索是"模糊理解",而精确查询是"铁面无私"的一对一比对。
⚙️ 核心机制:不分词 + 精确匹配
精确查询的执行逻辑非常直白:
-
索引时 :文档中的字段值(如果是
keyword类型)会作为一个完整的词条存入倒排索引。 -
查询时 :你输入的搜索词不会被分词,直接拿到倒排索引里查找完全相同的词条。
html
# term查询
GET /hotel/_search
{
"query":
{
"term":
{
"city": {
"value": "北京"
}
}
}
}
# range查询
GET /hotel/_search
{
"query":
{
"range":
{
"price": {
"gte": 900,
"lte": 2000
}
}
}
}
📋 常见精确查询类型
在日常开发中,最常用的精确查询主要有以下几种:
| 查询类型 | 描述 | 示例场景 |
|---|---|---|
term 查询 |
最核心的精确匹配,用于查找单个字段的精确值。 | 查询状态为 "已完成" 的订单;查找 age 等于 25 的用户。 |
terms 查询 |
term 的批量版,匹配字段值等于 给定数组中任意一个的文档。 |
查找状态为 "待支付" 或 "已取消" 的订单。 |
range 查询 |
查找字段值在指定数值或日期范围内的文档。 | 查找价格在 100-200 之间的商品;查找近7天的日志。 |
exists 查询 |
查找包含 指定字段(且值不为null)的文档。 |
查找所有填写了 email 字段的用户。 |
term 的变体 |
如 prefix(前缀匹配)、wildcard(通配符)、regexp(正则) |
查找所有以 "A" 开头的产品编码。 |

4.地理坐标查询
核心数据类型:geo_point
在进行任何地理查询前,索引中用于存储位置的字段类型必须是 geo_point。它支持多种经纬度格式:
-
对象格式 :
"location": {"lat": 41.12, "lon": -71.34} -
数组格式 :
"location": [-71.34, 41.12](注意:GeoJSON格式是经度在前,纬度在后) -
字符串格式 :
"location": "41.12,-71.34"(纬度在前,经度在后) -
GeoJSON格式 :
"location": {"type": "Point", "coordinates": [-71.34, 41.12]} -
WKT格式 :
"location": "POINT (-71.34 41.12)"
📌 主要的地理查询类型
Elasticsearch提供了几种主要的地理查询方式:
geo_distance查询:查找"附近"的位置
用于查找距某中心点指定距离内的所有文档。例如,查找(39.90, 116.65)坐标2公里 内的所有位置:距离单位可以是 km(公里)或 m(米)等
html
# distance 查询
GET /hotel/_search
{
"query": {
"geo_distance": {
"distance": "2km",
"location": "39.90,116.65"
}
}
}
geo_bounding_box查询:查找"矩形框"内的位置
用于查找落在指定矩形范围内的所有文档。需要提供矩形的左上角 和右下角两个点的坐标。例如,查找以下矩形框内的位置:
html
GET /my_locations/_search
{
"query": {
"bool": {
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": { "lat": 40.73, "lon": -74.1 },
"bottom_right": { "lat": 40.01, "lon": -71.12 }
}
}
}
}
}
}
5.组合查询
组合查询,在Elasticsearch中特指复合查询(Compound Query) ,它的核心作用是将多个独立的查询条件组合成一个整体,以实现更复杂的搜索逻辑





html
GET /hotel/_search
{
"query": {
"function_score": {
"query": {
"match": {
"all": "北京"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "如家"
}
},
"weight": 10
}
],
"boost_mode": "sum"
}
}
}

html
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{ "term": { "city": "北京" } }
],
"should": [
{ "term": { "brand.keyword": "7天酒店" } },
{ "term": { "brand.keyword": "速8" } }
],
"must_not": [
{"range": {"price": {"lte": 500}}}
],
"filter": [{"range": {"score": {"gte": 45}}}
]
}
}
}


4.查询结果处理
html
# 分数按照降序价格按照升序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{ "score":"desc"},
{ "price": "asc"}
]
}
# 按照经纬度升序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{ "_geo_distance": {"location": { "lat": 39.911, "lon": 116.395 },
"order": "asc",
"unit": "km"
}
}
]
}




html
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
},
"highlight": {
"fields": {
"all": {},
"name": {"require_field_match": "false"}
}
}
}

