unsetunset1、核心问题unset
unset
Elasticsearch 没有直接的"不包含"操作符,但我们可以通过组合 must_not 和其他查询方式来实现。
本文介绍 4 种实用方法,从灵活到高效依次递进。
unsetunset2、准备测试数据
unsetunset
创建一个订单日志索引:
PUT order-logs
{
"mappings": {
"properties": {
"content": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
image.png
插入几条测试数据:
POST _bulk
{ "index" : { "_index" : "order-logs", "_id" : "1" } }
{ "content" : "用户张三购买了iPhone15手机" }
{ "index" : { "_index" : "order-logs", "_id" : "2" } }
{ "content" : "用户李四购买了iPhone14手机" }
{ "index" : { "_index" : "order-logs", "_id" : "3" } }
{ "content" : "用户王五购买了华为Mate60手机" }
{ "index" : { "_index" : "order-logs", "_id" : "4" } }
{ "content" : "用户赵六购买了小米14手机" }
image.png
2.1 方法1: 正则表达式 (相对灵活)
适用场景: 需要复杂模式匹配时
需求: 排除所有包含 iPhone14 或 iPhone15 的订单
GET order-logs/_search
{
"query": {
"bool": {
"must_not": [
{ "regexp": { "content.keyword": ".*iPhone1[4-5].*" } }
]
}
}
}
返回结果:

"hits": [
{
"_index": "order-logs",
"_id": "3",
"_score": 0,
"_source": {
"content": "用户王五购买了华为Mate60手机"
}
},
{
"_index": "order-logs",
"_id": "4",
"_score": 0,
"_source": {
"content": "用户赵六购买了小米14手机"
}
}
]
}
}
缺点: 性能最差,仅在必须使用复杂模式时才选择
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战(多个项目) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;
演示地址:http://116.62.199.48:7070/
- 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
- 专栏阅读地址:https://www.quanxiaoha.com/column
截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4000+小伙伴加入
2.2 方法2: 通配符查询 (较快)
适用场景: 简单的子串匹配
需求: 排除所有包含"iPhone"的订单
GET order-logs/_search
{
"query": {
"bool": {
"must_not": [
{
"wildcard": {
"content.keyword": "*iPhone*"
}
}
]
}
}
}
返回结果:
"hits": [
{
"_index": "order-logs",
"_id": "3",
"_score": 0,
"_source": {
"content": "用户王五购买了华为Mate60手机"
}
},
{
"_index": "order-logs",
"_id": "4",
"_score": 0,
"_source": {
"content": "用户赵六购买了小米14手机"
}
}
]
}
image.png特点: 比正则快,但仍属于低性能操作
2.3 方法3: 查询字符串 (更简洁)
适用场景: 与方法2相同,但语法更简洁
POST order-logs/_search
{
"query": {
"bool": {
"must_not": [
{
"query_string": {
"query": "content:*iPhone*"
}
}
]
}
}
}
特点: 本质上也是通配符,但请求体更小
image.png2.4 方法4: 自定义分词器 + Match (最快)
适用场景: 提前知道要过滤的关键词,追求极致性能
核心思路: 建索引时配置分词器,让"iPhone15"被拆分成"iphone"、"iphone15"、"15"三个token
重建索引并配置分词器:
PUT order-logs-ext
{
"settings": {
"analysis": {
"analyzer": {
"content_analyzer": {
"tokenizer": "whitespace",
"filter": [
"lowercase",
"word_delimiter"
]
}
}
}
},
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "content_analyzer"
}
}
}
}
使用简单的 match 查询:
POST order-logs-ext/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"content": "iPhone"
}
}
]
}
}
}
优点: 性能最佳,比通配符和正则快得多
缺点:
索引配置复杂,只能匹配预设的分词规则 
unsetunset3、方法选择建议unset
unset
unset
unset4、实战建议unsetunset
开发测试阶段,咱们优先使用通配符或查询字符串,快速验证逻辑。
生产环境低频查询,可适当使用通配符。
生产环境高频查询,必须使用自定义分词器方案。
咱们企业的临时复杂需求,可以用正则,但要监控性能。
所有方法的核心都是 must_not 操作符 —— 它会反转匹配条件,把"包含"变成"不包含"。
前文全部案例均已在 Elasticsearch 9.0.0 版本验证成功。
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战(多个项目) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,
点击查看项目介绍;演示地址:http://116.62.199.48:7070/
- 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
- 专栏阅读地址:https://www.quanxiaoha.com/column
截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4000+小伙伴加入
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”
支持小哈呀,谢谢啦