Elasticsearch 进阶
2026/9/10 23:40:24 网站建设 项目流程
特性Low-Level REST ClientHigh-Level REST ClientJava 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查询的分类可以从三个层面理解:

  1. 广义概念:分为外部DSL内部DSL

  2. 结构上:分为叶子查询复合查询

  3. 功能上:叶子查询可进一步分为全文检索精确查询地理查询等。

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

2.全文检索查询

全文检索(Full-Text Search)是搜索引擎和数据库中最核心的查询方式之一,它不是为了进行简单的“字符串匹配”,而是为了进行理解内容含义的“语义”搜索

💡 什么是全文检索?

简单来说,全文检索的过程就像查字典:

  1. 建立索引(查字典前的准备工作):系统会像编写字典的“索引页”一样,扫描文档中的每一个词,为它们建立索引。这个索引会记录每个词出现在哪些文档、以及出现的次数和位置。这个索引结构通常被称为“倒排索引”(Inverted Index)。

  2. 执行搜索(根据索引查内容):当你输入关键词查询时,系统不会去原文里逐字扫描,而是直接去“倒排索引”这个目录里快速查找,然后返回包含这些词的文档。

这种“先建目录,再查目录”的方式,让检索效率远高于传统的LIKE模糊匹配。

⚙️ 核心原理:分词与倒排索引

全文检索之所以能“理解”你的搜索,主要依赖两个关键技术:

  • 分词(Analysis):在建立索引和执行搜索时,系统都会用分词器(Analyzer)将文本切分成一个个独立的词条(Term)。例如,“我爱北京天安门”会被切分为“我”、“爱”、“北京”、“天安门”等词条。

  • 倒排索引(Inverted Index):这是全文检索速度的保证。它是一个词条到文档ID的映射表,能快速定位包含特定词条的所有文档。

📋 常见查询类型(以Elasticsearch为例)

在实际使用中,最常见的全文检索查询类型如下:

查询类型描述适用场景
match查询最基础、最核心的全文查询。会对输入进行分词,然后搜索任意一个分词结果。绝大多数常规的搜索场景,如电商、博客的搜索框。
match_phrase查询短语匹配。不仅要求所有词出现,还要求它们的顺序和位置必须一致。搜索精确的短语,如“机器学习”、“中华人民共和国”。
multi_match查询match查询的多字段版本。可以在多个字段(如标题、内容、标签)中同时搜索。不确定关键词在哪个字段,需要在多个字段中综合搜索。
query_string查询支持复杂的语法,如布尔逻辑(ANDORNOT)、通配符等。提供给有经验的高级用户,进行精确、复杂的搜索。
simple_query_string查询query_string简化、更健壮版本。对语法错误容忍度更高,更适合面向普通用户。直接暴露给终端用户的搜索框,避免因用户输入特殊字符导致报错。
intervals查询高级匹配。可以对匹配词项的顺序和邻近度(Proximity)进行精细控制法律、学术等对文本位置关系有严格要求的专业搜索。

此外,还有一些特定场景的变种,如match_phrase_prefix常用于搜索框的自动补全(Auto-complete)功能。

💎 总结:全文检索 vs. 精确查询

理解全文检索,关键在于区分它和精确查询(Term Query)

  • 处理方式:全文检索会对输入文本进行分词;而精确查询不会,它将输入作为一个整体。

  • 搜索目标:全文检索搜索的是分词后的词条;精确查询搜索的是未经处理的完整词条

  • 主要用途:全文检索用于相关性搜索,如Google、百度;精确查询用于过滤,如查找特定ID、状态、精确分类等。

# 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),直接去倒排索引中匹配。

简单来说,全文检索是“模糊理解”,而精确查询是“铁面无私”的一对一比对。


⚙️ 核心机制:不分词 + 精确匹配

精确查询的执行逻辑非常直白:

  1. 索引时:文档中的字段值(如果是keyword类型)会作为一个完整的词条存入倒排索引。

  2. 查询时:你输入的搜索词不会被分词,直接拿到倒排索引里查找完全相同的词条。

# 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提供了几种主要的地理查询方式:

1.geo_distance查询:查找“附近”的位置

用于查找距某中心点指定距离内的所有文档。例如,查找(39.90, 116.65)坐标2公里内的所有位置:距离单位可以是km(公里)或m(米)等

# distance 查询 GET /hotel/_search { "query": { "geo_distance": { "distance": "2km", "location": "39.90,116.65" } } }

2.geo_bounding_box查询:查找“矩形框”内的位置

用于查找落在指定矩形范围内的所有文档。需要提供矩形的左上角右下角两个点的坐标。例如,查找以下矩形框内的位置:

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),它的核心作用是将多个独立的查询条件组合成一个整体,以实现更复杂的搜索逻辑

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

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.查询结果处理

# 分数按照降序价格按照升序 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" } } ] }

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询