Py学习  »  Elasticsearch

Elasticsearch 实现"不包含"查询的 4 种方法,你知道几个?

小哈学Java • 1 周前 • 27 次点击  

unsetunset1、核心问题unset unset

Elasticsearch 没有直接的"不包含"操作符,但我们可以通过组合 must_not 和其他查询方式来实现。

本文介绍 4 种实用方法,从灵活到高效依次递进。

unsetunset2、准备测试数据 unsetunset

创建一个订单日志索引:

PUT order-logs
{
"mappings": {
    "properties": {
      "content": {
        "type""text",
        "fields": {
          "keyword": {
            "type""keyword"
          }
        }
      }    
    }
  }
}
image.png
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
image.png

2.1 方法1: 正则表达式 (相对灵活)

适用场景:  需要复杂模式匹配时

需求:  排除所有包含 iPhone14 或 iPhone15 的订单

GET order-logs/_search
{
  "query": {
    "bool": {
      "must_not": [
         { "regexp": { "content.keyword"".*iPhone1[4-5].*" } }
      ]
    }
  }
}

返回结果:  image.png

  "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
image.png

特点:  比正则快,但仍属于低性能操作

2.3 方法3: 查询字符串 (更简洁)

适用场景:  与方法2相同,但语法更简洁

POST order-logs/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "query_string": {
            "query""content:*iPhone*"
          }
        }
      ]
    }
  }
}

特点:  本质上也是通配符,但请求体更小

image.png
image.png

2.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"
      }
    }
  }
}

image.png image.png  使用简单的 match 查询:

POST order-logs-ext/_search
{
"query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "content""iPhone"
          }
        }
      ]
    }
  }
}

优点:  性能最佳,比通配符和正则快得多
缺点:   索引配置复杂,只能匹配预设的分词规则  image.png

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+小伙伴加入

图片


图片
图片

1.  我的私密学习小圈子,从0到1手撸企业实战项目~

2. Postman替代品:一款极简的网页版 API 调试神器!

3. MySQL的6大雷区,99%的人会踩中!

4. 改变习惯性 !=null 判空,只需一秒!

图片

最近面试BAT,整理一份面试资料Java面试BATJ通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。

“在看” 支持小哈呀,谢谢啦

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/188499