Elasticsearch 进阶

特性 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查询的分类可以从三个层面理解:

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

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

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

html 复制代码
# 查询所有
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、状态、精确分类等。

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

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


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

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

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

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

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

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

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

html 复制代码
# distance 查询
GET /hotel/_search
{
  "query": {
    "geo_distance": {
      "distance": "2km",
      "location":  "39.90,116.65"
      }
    }
}
  1. 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"}
    }
  }
}
相关推荐
xqqxqxxq1 小时前
AI Agent学习:第四章小结及八道思考题(李博杰《深入理解 AI Agent》第四章观后总结)
大数据·人工智能·学习
汇海老周1 小时前
《金融炼金术》第三课:从反身性到繁荣—萧条——理解正反馈机制
大数据·金融
Aloudata1 小时前
语义治理 vs 知识治理:AI 数据分析需要业务知识库还是可执行语义层
大数据·人工智能·数据分析·data agent·语义层
en.en..1 小时前
Linux wait()函数(预防僵尸进程)
java·大数据·开发语言
Superzhangaa1 小时前
全国服务消费季里的科技新品:太希智能外骨骼持续走红
大数据·人工智能·科技·开源
凡泰AI2 小时前
如何为政务 APP 搭建开放平台,实现多部门、第三方供应商标准化入驻与统一管理
android·大数据·小程序·uni-app·app·政务
人工智能培训2 小时前
从“捏泥人”到“造世界”:3D生成式AI的技术跃迁与产业落地
大数据·人工智能·学习·生活·ai写作
天远Date Lab2 小时前
零信任架构实战:基于天远全能个人大数据报告构建自动化核心KYC网关
大数据·人工智能·架构·自动化
盛世宏博智慧档案2 小时前
基于PLC与物联网网关的档案库房温湿度超标自动联动控制实现思路(含拓扑图与协议对接)
大数据·人工智能·物联网