大数据-175 Elasticsearch Term 精确查询与 Bool 组合实战:range/regexp/fuzzy 全示例

TL;DR

  • 场景:业务既有精确匹配(价格、ID、时间),又有容错需求(前缀、模糊、错别字)。
  • 结论:用 term-level queries 处理结构化精确条件,再用 bool 组合 must/filter/should/must_not。
  • 产出:给出从建索引、写入数据到 term/terms/range/exists/prefix/regexp/fuzzy/ids/bool 全流程 DSL 示例。

版本矩阵

项目 说明
Elasticsearch 7.x 按文中 DSL 在 7.x 环境完成验证,索引创建与 term-level queries 可直接复用。
Elasticsearch 8.x 查询 DSL 语法保持兼容,注意结合实际集群的 default mappings 与日期格式配置。
IK 分词插件(7.x/8.x) 示例依赖 ik_max_word 分词器,需在集群中预先安装并在 settings 中启用。
Dev Tools / Kibana 控制台 所有示例基于 Dev Tools 控制台执行,适合本地或测试环境快速跟跑与调试。

可以使用term-level queries根据结构化数据中的精确值查找文档。结构化数据的值包括日期范围、IP地址、价格或者产品ID。 与全文查询不同,term-level queries不分析搜索词。相反,词条与存储在字段级别中的术语完全匹配。

初始索引

新建一个book一个索引:

json 复制代码
# 新建book索引
PUT /book
{
  "settings": {},
  "mappings" : {
    "properties" : {
      "description" : {
        "type" : "text",
        "analyzer" : "ik_max_word"
      },
      "name" : {
        "type" : "text",
        "analyzer" : "ik_max_word"
      },
      "price" : {
        "type" : "float"
      },
      "timestamp" : {
        "type" : "date",
        "format" : "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

执行的结果如下图所示:

写入数据

生成几条数据用作我们后续的测试:

json 复制代码
# 新增数据1
PUT /book/_doc/1
{
  "name": "lucene",
  "description": "Lucene Core is a Java library providing powerful indexing and search features, as well as spellchecking, hit highlighting and advanced analysis/tokenization capabilities. The PyLucene sub project provides Python bindings for Lucene Core. ",
  "price":100.45,
  "timestamp":"2020-08-21 19:11:35"
}

# 新增数据2
PUT /book/_doc/2
{
  "name": "solr",
  "description": "Solr is highly scalable, providing fully fault tolerant distributed indexing, search and analytics. It exposes Lucenes features through easy to use JSON/HTTP interfaces or native clients for Java and other languages.",
  "price":320.45,
  "timestamp":"2020-07-21 17:11:35"
}

# 新增数据3
PUT /book/_doc/3
{
  "name": "Hadoop",
  "description": "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models.",
  "price":620.45,
  "timestamp":"2020-08-22 19:18:35"
}

# 新增数据4
PUT /book/_doc/4
{
  "name": "ElasticSearch",
  "description": "Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。",
  "price":999.99,
  "timestamp":"2020-08-15 10:11:35"
}

执行的结果如下图所示:

词条搜索(term query)

term查询用于查询指定字段包含某个词项的文档

json 复制代码
# term是精确检索 多一个少一个都不行
POST /book/_search
{
  "query": {
    "term" : { 
      "name" : "solr" 
    }
  }
}

执行的结果如下图所示:

词条集合搜索(terms query)

terms 查询用于查询指定字段包含某些词项的文档

json 复制代码
# 要有检索内容的name中有solr、elasticsearch,多个条件
POST /book/_search
{
  "query": {
    "terms" : { 
      "name" : ["solr", "elasticsearch"]
    }
  }
}

执行的结果如下图所示:

范围搜索(range query)

  • gte 大于等于
  • gt 大于
  • lte 小于等于
  • lt 小于
  • boost 查询权重 在多条件查询时,可以手动控制每个条件的比重
json 复制代码
# 范围检索 可以加权
POST /book/_search
{
  "query": {
    "range" : {
      "price" : {
        "gte" : 10,
        "lte" : 200,
        "boost" : 2.0
      }
    }
  }
}

执行结果如下图所示: 继续执行:

json 复制代码
# 范围检索 也可以指定格式
POST /book/_search
{
  "query": {
    "range" : {
      "timestamp" : {
        "gte": "18/08/2020",
        "lte": "2021",
        "format": "dd/MM/yyyy||yyyy"
      }
    }
  }
}

执行结果如下图所示:

不为空搜索(exists query)

查询指定字段不为空的文档,相当于SQL中的 column is not null

json 复制代码
# 不为空检索
POST /book/_search
{
  "query": {
    "exists" : { "field" : "price" }
  }
}

执行结果如下图所示:

词项前缀搜索(prefix query)

json 复制代码
# 检索以xx开头的数据
POST /book/_search
{
  "query": {
    "prefix" : { 
      "name" : "so" 
    }
  }
}

执行结果如下图所示:

正则搜索(regexp query)

regexp允许使用正则表达式进行term查询,注意regexp如果使用不正确,会给服务器带来很严重的性能压力,比如*开头的查询,将会匹配所有倒排索引中的关键字,这几乎是全表扫描,因此如果可以的话,最好使用正则前,加上匹配的前缀。

json 复制代码
# 正则匹配
POST /book/_search
{
  "query": {
    "regexp":{
      "name": "s.*"
    }
  }
}

执行的结果如下图所示: 这里也可以加入 boost值来控制:

json 复制代码
# 正则匹配 boost额外加权
POST /book/_search
{
  "query": {
    "regexp":{
      "name":{
        "value":"s.*",
        "boost":1.2
      }
    }
  }
}

执行结果如下图所示:

模糊搜索(fuzzy query)

json 复制代码
# fuzzy 可以搜索到结果 solr
POST /book/_search
{
  "query": {
    "fuzzy" : { 
      "name" : "sol" 
    }
  }
}

# 搜索不到结果 匹配不到 因为匹配字母数不够
POST /book/_search
{
  "query": {
    "fuzzy" : { 
      "name" : "so" 
    }
  }
}

# 通过 fuzziness 设置匹配字母的数量
# 设置2个就可以从 so匹配到solr了
POST /book/_search
{
  "query": {
    "fuzzy" : {
      "name" : {
        "value": "so",
        "fuzziness": 2
      }
    }
  }
}

执行结果如下图1所示: 执行结果图2如下图所示:

继续准备执行:

json 复制代码
# 写错字母顺序也可以匹配到(默认错1个)
POST /book/_search
{
  "query": {
    "fuzzy" : {
      "name" : {
        "value": "sorl"
      }
    }
  }
}

# 写错字母顺序多了匹配不到(超过了1个)
POST /book/_search
{
  "query": {
    "fuzzy" : {
      "name" : {
        "value": "rlso"
      }
    }
  }
}

# 通过fuzziness 设置错误的字母数量
POST /book/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "osrl",
        "fuzziness":2
      }
    }
  }
}

运行结果图1如下图所示:

运行结果图2如下图所示:

ids搜索(id集合查询)

json 复制代码
# 根据ID查询
POST /book/_search
{
  "query": {
    "ids" : {
      "values" : ["1", "3"]
    }
  }
}

执行的结果如下图所示:

复合搜索(compound query)

布尔搜索(bool query)

bool 查询操作来组合查询子句为一个查询,可用关键字:

  • must 必须满足
  • filter 必须满足,对集合包含/排除进行简单检查,速度非常快,不参与也不影响评分结果
  • should 或关系
  • must_not 必须不满足,在filter上下文中执行,不参与、不影响评分

假设我们有一个需求是:

  • description中必须有Java
  • price必须满足大于100小于1000
  • name字段可以是lucene或者solr的一种即可
  • 时间满足某个时间节点

那么对应的DSL如下:

json 复制代码
# 根据业务条件 编写的DSL
POST /book/_search
{
  "query": {
    "bool": {
      "filter": {
        "match": { 
          "description": "java" 
        }
      },
      "must": [
        {
          "range": {
            "price": {
              "gte": 100,
              "lte": 1000
            }
          }
        },
        {
          "bool": {
            "should": [
              {
                "term": {
                  "name": "lucene"
                }
              },
              {
                "term": {
                  "name": "solr"
                }
              }
            ]
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "timestamp": {
              "gte": "18/08/2020",
              "lte": "2021",
              "format": "dd/MM/yyyy||yyyy"
            }
          }
        }
      ]
    }
  }
}

执行结果如下图所示:

错误速查

症状 根因定位 修复
termtext 字段中文内容命中率极低 text 字段被分词,term 按分词后的 token 精确匹配,和自然语言不一致 查看 mappings"type": "text",并检查 analyzer 配置 精确匹配用 .keyword 子字段或将字段改为 keyword;全文搜索改用 match / match_phrase
range 查询日期无结果或报日期解析错误 gte/lte 的日期字符串和字段 format 不匹配 查看字段 format 配置与报错日志中的期望格式 调整 DSL 中日期格式与 mappings 中的 format 保持一致,必要时补充多格式(如 yyyy-MM-dd)。
exists 查询命中数异常少,部分预期数据缺失 字段实际未写入、字段名拼写错误或被动态映射为对象/嵌套结构 _source 查看原始文档结构,确认字段路径与名称 修正字段名或写入逻辑;如为嵌套结构需调整字段路径或使用 nested/脚本查询。
prefix / regexp 查询占用 CPU 高、响应慢 在高基数字段上做前缀/正则扫描,且正则以 * 开头或缺少前缀,接近全表扫描 通过 _tasks、慢查询日志、监控看到该 DSL 的耗时和资源消耗 尽量添加固定前缀,避免 .*xxx 这种模式;对高基数字段改用倒排友好的前缀设计或加缓存/限流。
fuzzy 查询返回结果不稳定或耗时明显上升 fuzziness 设置过大,允许的编辑距离过高,候选词空间迅速放大 查看 DSL 中 fuzziness 配置并结合 explain/profile 分析查询计划 控制 fuzziness 在 1--2;对高频、大词典字段慎用 fuzzy,必要时改为前缀或拼写纠错离线字典。
bool 查询结果比预期多或少,评分排序异常 混淆 mustshouldfiltermust_not 语义,或 minimum_should_match 未设置 在 Dev Tools 中加 "explain": true 或使用 Profile API 查看子句参与评分方式 精确区分:过滤用 filter,必须条件用 must,可选加分用 should,排除用 must_not,并设置 minimum_should_match
ids 查询部分 ID 无法命中 写入时 ID 为字符串/数值混用或索引名、type 与查询不一致 _doc/{id} 单独 GET 验证单条是否存在,核对索引前缀 /book/_search 是否正确 保持 ID 类型一致;确认索引名称与路径正确,必要时通过 alias 统一访问入口。

其他系列

🚀 AI篇持续更新中(长期更新)

AI炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究 ,持续打造实用AI工具指南! AI研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地

💻 Java篇持续更新中(长期更新)

Java-180 Java 接入 FastDFS:自编译客户端与 Maven/Spring Boot 实战 MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务已完结,Dubbo已完结,MySQL已完结,MongoDB已完结,Neo4j已完结,FastDFS 已完结,OSS正在更新... 深入浅出助你打牢基础! Java模块直达链接](blog.csdn.net/w776341482/...)

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈! 大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

相关推荐
甜鲸鱼1 小时前
【Spring Boot + OpenAPI 3】开箱即用的 API 文档方案(SpringDoc + Knife4j)
java·spring boot·后端
foxsen_xia1 小时前
go(基础10)——错误处理
开发语言·后端·golang
小码哥0681 小时前
企业灵活用工小程序(解析+源码)
大数据·企业灵活用工·灵活用工·企业用工·用工系统
Deepoch1 小时前
发动机设计迎突破!Deepoc-M低幻觉模型重塑研发逻辑
大数据·人工智能·deepoc
sendnews1 小时前
红松亮相首届厦门银博会,以一站式社区平台展示退休生活新图景
大数据·人工智能
有Li1 小时前
一种交互式可解释人工智能方法,用于改进数字细胞病理学癌症亚型分类中的人机协作|文献速递-文献分享
大数据·论文阅读·人工智能·文献
是店小二呀1 小时前
openEuler多核压缩性能实战:从单核到多核的算力跃升
后端
是店小二呀1 小时前
openEuler 上 Redis 性能调优与基准测试实战
后端
是店小二呀1 小时前
openEuler 25.09 系统级开发环境配置与实践(GCC + GDB + SDK)
后端