文章二十一:ElasticSearch 词项查询与调度查询实战

term

定义:

term :用于查询 字段精确等于单个指定值 的文档,无分词、无模糊,完全精准匹配。

等价 SQL 逻辑:where 字段 = 目标值.term 严禁用于 text 分词字段,仅适配:

  • 精准字符串:keyword 类型

  • 数值类型:int、long、float、double

  • 布尔类型:boolean

  • 日期类型:date

term 全部官方常用参数

term 查询支持5个官方核心参数,包含高频实用参数与进阶控制参数,全覆盖开发、面试所需,所有参数均为查询级别配置,无需修改索引 Mapping:

① value(必填)

作用:指定需要精准匹配的目标值,支持字符串、数值、布尔、日期等类型。

注意:严格不分词,必须和索引存储的原始值一致(默认区分大小写)。

② boost(权重可选)

作用:设置当前查询的权重,控制文档评分(_score),实现结果排序加权。

默认值:1.0,数值越大权重越高,排名越靠前。

③ case_insensitive(忽略大小写可选,ES7.10+)

作用:查询时动态忽略大小写,无需修改索引结构,临时适配大小写不敏感的精准匹配。

默认值:false(严格区分大小写)。

④ _name(查询标记可选)

作用:给当前 term 查询命名,用于标识命中来源,方便多条件复杂查询时调试、过滤命中规则。

⑤ ignore_unmapped(忽略未映射字段可选)

作用:适配多索引查询,若查询字段不存在(未映射),不报错、直接忽略该查询条件。

默认值:false(字段不存在直接抛错)。

terms

定义

terms :用于查询 字段值匹配列表中任意一个值 的文档,多个值之间是 OR 或逻辑

等价 SQL 逻辑:where 字段 IN (值1,值2,值3...)

适用场景

需要同时筛选多个精准枚举值的场景,例如:多个状态码、多个标签、多个分类 ID 等。

全部官方常用参数(完整版)

terms 作为多值精准查询,同样支持专属拓展参数,大部分参数与 term 通用,同时具备独有特性,全覆盖开发场景:

① value 数组(必填)

作用:传入多个精准匹配值,数组内为 OR 逻辑,匹配任意一个即命中。

② boost(权重可选)

作用:统一设置当前 terms 查询的权重,提升整体命中文档的评分。

③ _name(查询标记可选)

作用:标记当前 terms 查询,用于复杂 bool 查询调试。

④ ignore_unmapped(忽略未映射字段可选)

作用:多索引查询时,字段不存在则忽略,避免报错。

重点考点:terms 不支持 case_insensitive!

官方明确规定:只有 term 单值查询拥有 case_insensitive 参数,terms 多值查询无该参数,无法直接查询级忽略大小写。

✅ terms 忽略大小写解决方案:索引 Mapping 配置 normalizer 标准化器(全局小写)。

terms_lookup

terms_lookup 是 Elasticsearch 中 terms 多值精准查询的高级扩展功能

普通 terms 查询需要手动把所有匹配值写在查询 DSL 中 ,而 terms_lookup 可以直接「从另一个索引的文档中动态读取匹配值列表」,自动完成多值 IN 查询。

通俗理解:

  • 普通 terms:field : [100,200,300,400...] 手动写死数组

  • terms_lookup:不用写数组,告诉 ES「去某某索引、某某文档、某某字段,把里面的数组值拿过来当查询条件」

等价 SQL 语义:WHERE id IN (SELECT id FROM 另一张表 WHERE ...)

全部参数详解

terms_lookup 一共 4 个参数,3 个必填、1 个选填。

1. index(必填)

需要读取值来源的索引名称

告诉 ES:去哪里找参考数据。

2. id(必填)

来源索引中,存储值列表的文档 ID

告诉 ES:找哪一条文档。

3. path(必填)

来源文档中,存放多值列表的字段名

告诉 ES:取哪个字段的数组作为查询条件。

4. routing(可选/条件必填)

如果写入来源文档时使用了自定义 routing,查询时必须携带相同 routing,否则找不到文档。

无自定义路由场景,直接省略。

使用案例:

复制代码
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "sku": {
              "index": "kibana_sample_data_ecommerce",
              "id": "ZojV6J0B-pnYIe9U9Qb7",
              "path": "sku"
            }
          }
        }
      ]
    }
  }
}

terms_set

terms_set 是 Elasticsearch 精准词项查询(Term-level Query) 中的高级查询,是普通 terms 查询的增强版。

原生 terms 只能实现 任意匹配(OR),只要命中一个关键词就返回数据;

terms_set可以实现 阈值匹配必须至少匹配 N 个关键词才返回数据

通俗一句话区别:

  • terms:沾一个就中(宽松)

  • terms_set:够数量才中(精准可控)

对应业务逻辑:介于 OR(或)AND(且) 之间的「部分匹配、相似度匹配」。

典型场景:标签匹配、技能匹配、兴趣相似度、多属性弱匹配筛选。

核心使用前提

terms_set 只能作用于「数组类型字段」

例如:tags、skills、labels、category 等多值字段。

原理:文档字段是数组、查询词也是数组,ES 计算两者交集个数,和阈值对比判断是否命中。

全部核心参数详解

terms_set 拥有 1个必填参数 + 两组二选一阈值参数 + 通用拓展参数

1. terms(必填)

需要匹配的关键词数组列表,精准不分词匹配,和普通 terms 的 terms 数组用法一致。

2. 阈值二选一(核心)

terms_set 不能直接写固定数字,只能通过两种方式定义最小匹配数:

方式一:minimum_should_match_field(静态字段阈值)

读取文档自身的数值字段作为最小匹配阈值。

特点:每一条文档可以有自己独立的匹配门槛,灵活适配个性化规则。

方式二:minimum_should_match_script(动态脚本阈值)

通过 Painless 脚本动态计算最小匹配数。

内置系统变量:params.num_terms,代表本次查询传入的关键词总数量。

可以实现:按比例匹配、保底匹配、动态计算等复杂逻辑。

3. 通用拓展参数

  • boost:设置查询权重,提升文档评分权重

  • _name:查询别名,用于复杂 bool 查询调试定位

  • ignore_unmapped:忽略未映射字段,查询不报错、容错执行

两套完整可运行实战案例

案例1:minimum_should_match_field 文档字段阈值

业务场景:人才技能匹配,每个人才简历设置了「最低需要匹配的技能数」

测试数据写入:

复制代码
PUT talent_index/_doc/1 { "skills": ["Java", "MySQL", "Linux"], "e": 2 } PUT talent_index/_doc/2 { "skills": ["Java", "Redis"], "min_match": 2 } PUT talent_index/_doc/3 { "skills": ["Python", "Nginx"], "min_match": 1 } 

查询需求:筛选出匹配 Java、MySQL、Redis 且满足个人最低匹配数的简历

复制代码
GET talent_index/_search { "query": { "terms_set": { "skills": { "terms": ["Java", "MySQL", "Redis"], "minimum_should_match_field": "min_match" } } } } 

结果解析

  • 文档1:命中 Java、MySQL(2个)≥ 2 → 命中

  • 文档2:命中 Java、Redis(2个)≥ 2 → 命中

  • 文档3:无匹配技能 → 不命中

案例2:minimum_should_match_script 动态比例阈值

业务场景:统一规则,无需额外字段,实现「匹配总数60%且至少匹配2个」的相似度筛选

复制代码
GET talent_index/_search { "query": { "terms_set": { "skills": { "terms": ["Java", "MySQL", "Redis", "Linux"], "minimum_should_match_script": { "source": "Math.max(2, params.num_terms * 0.6)" } } } } } 

脚本逻辑

  • params.num_terms = 4

  • 4 * 0.6 = 2.4

  • 取最大值 2.4 → 最少匹配3个关键词才命中

Fuzzy查询

Fuzzy 查询是 ES 用于解决文本拼写错误、形近词、输入误差 的全文检索方案,基于**莱文斯坦距离(编辑距离)**实现,支持在可容忍的字符误差范围内匹配目标文档。

复制代码
GET index_test/_search
{
  "query": {
    "match": {
      "FIELD": {
        "query": "hgdfkjs",
        "fuzziness": 1,
        "max_expansions": 10 #最多可以使用纠错处理多少个单词
      }
    }
  }
}

prefix 查询:

复制代码
GET index_test/_search
{
  "_source": ["DestWeather"], 
  "query": {
    "prefix": {
      "DestWeather.keyword": {
        "value": "R"
      }
    }
  }
}

wildcard:

wildcard 就是 ES 专门给【通配符查询】设计的专用语法 ,它只做通配符匹配

  • * 匹配任意多个字符
  • ? 匹配任意一个字符

没有分词、没有语义、没有纠错 ,就是纯字符串模式匹配

复制代码
GET index_test/_search
{
   "_source": ["Carrier"], 
   "query": {
     "wildcard": {
       "Carrier.keyword": {
         "value": "Kibana*"
       }
     }
   }
}
查询 作用 分词? 原理 性能
prefix 前缀匹配 ❌ 不分词 倒排索引快速查找 最快
wildcard 通配符匹配 ❌ 不分词 字符串模式匹配 中等
fuzzy 拼写纠错 ❌ 不分词 编辑距离计算 最慢

wildcard 字段类型拓展讲解

  1. wildcard 字段类型 :ES 字段数据类型,专门替代 keyword 做通配、前缀、模糊场景存储
  2. wildcard:内部会构建优化型字符串索引,天然适配:
  • 前缀查询 prefix
  • 通配符 wildcard
  • 后缀匹配、中间模糊匹配

核心特性

  1. 不分词,和 keyword 一致,存储完整原始字符串;

  2. 不适合大段长文本,适合短字符:手机号、编码、型号、城市名、昵称;

  3. 针对模糊 / 通配场景做索引优化,通配查询远快于 keyword

  4. 不依赖分词器,纯原始字符匹配。

    PUT test_idx
    {
    "mappings": {
    "properties": {
    "city_name": {
    "type": "wildcard"
    }
    }
    }
    }

exists

查找数据中存在当前字段的数据信息。

复制代码
GET index_test/_search
{
  "query": {
    "exists": {
      "field": "Carrier"
    }
  }
}

ids:

基于id进行查询,类似于mget

复制代码
GET index_test/_search
{
  "query": {
    "ids": {
      "values": ["QojV6J0B-pnYIe9U-Qwl","Q4jV6J0B-pnYIe9U-Qwl"]
    }
  }
}

regexp

不建议使用,是在是没有办法解决时,使用这个

复制代码
GET index_test/_search
{
  "query": {
    "regexp": {
      "DestWeather.keyword": {
        "value": "R.*",
        "flags": "ALL"
      }
    }
  }
}

Span跨度查询:

Span 查询是 Elasticsearch 面向词条位置、语序、间隔距离 的精细化底层全文检索方案,依托索引分词后保留的词条位置偏移量实现匹配,严格约束检索词条的先后顺序、相邻间隔、段落范围与组合逻辑,适用于高精度短语、邻近词、固定语序类专业检索场景。

Span 查询 核心分类

1. span_term 【基础原子查询】

作用:精准匹配单个分词词条,是所有 Span 组合查询的最小单元。

  • 等价 term 查询

  • 大小写敏感

  • 仅匹配完整分词 term

    {
    "span_term": {
    "content": "elasticsearch"
    }
    }


2. span_near 【高频核心:邻近词匹配】

最常用的 Span 查询,控制多个词条之间的间隔距离、先后顺序。关键参数:

  • clauses:多个 span 子查询集合

  • slop:允许中间间隔的最大单词数量

  • in_order:是否强制要求词条按书写顺序出现

    {
    "span_near": {
    "clauses": [
    {"span_term": {"content": "spring"}},
    {"span_term": {"content": "boot"}}
    ],
    "slop": 2,
    "in_order": true
    }
    }

释义:必须先后出现 springboot,中间最多间隔 2 个无关词汇。


3. span_first 【开头位置限制】

限定词条必须出现在文档前 N 个分词范围内,用于匹配开头关键内容。

复制代码
GET index_test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "span_first": {
            "match": {
              "span_term": {
                "Dest": "airport"
              }
            },
            "end": 2
          }
        }
      ]
    }
  }
}

4. span_or /span_not/span_and 【逻辑组合】

  • span_or:多个 span 条件满足任意一个即可
  • span_and:多个 span 条件必须同时满足
  • span_not:匹配 A 条件、同时排除 B 条件

用于复杂业务规则叠加。


5. span_multi 【模糊类嵌套组合|重点】

打通 Span 与模糊体系的关键查询;可以嵌套:fuzzyprefixwildcardregexp实现「拼写纠错 + 位置约束」双重能力

复制代码
{
  "span_near": {
    "clauses": [
      {
        "span_multi": {
          "match": {
            "fuzzy": {
              "content": {
                "value": "elastc",
                "fuzziness": 1
              }
            }
          }
        }
      },
      {"span_term": {"content": "search"}}
    ],
    "slop": 1,
    "in_order": true
  }
}

业务价值:先通过 Fuzzy 修正拼写错误,再强制两个词邻近有序出现,弥补普通模糊查询无位置控制的缺陷。

script脚本查询

复制代码
GET index_test/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "script": {
            "script": {
              "source": "doc['Dest.keyword'].value.length() > 10"
            }
          }
        }
      ]
    }
  }
}

script_score脚本打分

script_score 是 ES 用于自定义搜索结果分数的查询方案,通过 Painless 脚本编写动态算分公式(字段相加、相乘、条件判断),完全替换或修改 ES 默认相关性分数,实现业务规则驱动的搜索排序。

复制代码
GET index_test/_search
{
  "query": {
    "script_score": {
      "script": {
        "source": """
        doc['FlightTimeMin'].value+doc['FlightDelayMin'].value
        """
      },
      "query": {
        "match": {
          "Dest": "Kingsford"
        }
      }
    }
  }
}

pinned固定查询

Pinned 固定查询 是 Elasticsearch 提供的结果强制置顶检索方案,支持指定固定文档 ID,在检索结果中将目标文档强制排在最前列,不受默认相关性打分、脚本算分、业务权重排序影响,常用于首页置顶、精选内容、指定商品优先展示等业务场景。

复制代码
GET index_test/_search
{
  "query": {
    "pinned": {
      "ids": ["OIjV6J0B-pnYIe9U-Q0m","QojV6J0B-pnYIe9U-Qwl","pIjV6J0B-pnYIe9U-Qwl"],  
      "organic": {
        "match": {
          "Dest": "Kingsford"
        }
      }
    }
  }
}

参数解释

  • ids:需要强制置顶的文档主键 ID
  • organic:原生普通查询(正常检索条件)

执行逻辑

  1. 先正常执行 organic 内的 match 查询,命中所有数据
  2. ids 内的文档,强制置顶在结果头部
  3. 其余文档,按原有相关性分数 / 排序规则正常展示
相关推荐
Bechamz1 小时前
大数据开发学习Day25
java·大数据·学习
AI周红伟1 小时前
AI学习第一课:OpenClaw企业实战应用工作坊
大数据·人工智能
摇滚侠1 小时前
数据聚合 黑马 Elasticsearch 全套教程,黑马旅游网案例
大数据·elasticsearch·搜索引擎
李李李勃谦1 小时前
鸿蒙PCBI 报表工具:连接数据库与可视化报表生成
数据库·华为·交互·harmonyos
咖啡八杯2 小时前
GoF设计模式——单例模式
java
0xDevNull2 小时前
JDK多版本切换安装与配置
java·后端
czlczl200209252 小时前
MAX()和MIN()优化
数据库·mysql·性能优化
流年似水~2 小时前
Java新手5分钟接AI:Spring AI Alibaba实战
java·人工智能·spring