You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Elasticsearch中实现多字段不区分大小写的部分匹配?

实现Elasticsearch类似SQL ILIKE '%test%'的搜索方案

问题分析

你要实现的是任意位置的模糊匹配(类似ILIKE '%test%'),之前的query_string虽然能实现但存在性能和安全风险(用户输入的特殊字符可能引发查询语法错误);multi_match默认不生效是因为标准分词器无法拆分出嵌入在单词中的子串(比如mytest不会被拆出test);错误配置的ngram分词器会生成过多短token,导致匹配所有无关文档。

方案一:Wildcard + Bool Should(快速实现,适合小数据量)

这种方式无需修改索引映射,直接通过wildcard查询结合bool的should子句实现多字段模糊匹配,且比query_string更安全(不会解析特殊查询语法)。

查询示例

{
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "brand": {
              "value": "*test*",
              "case_insensitive": true
            }
          }
        },
        {
          "wildcard": {
            "name": {
              "value": "*test*",
              "case_insensitive": true
            }
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}
  • case_insensitive(7.10+版本支持):自动处理大小写匹配,无需提前转义输入内容。
  • 注意:如果数据量极大,前缀*会导致Elasticsearch遍历大量倒排索引项,性能会明显下降,这种情况建议使用方案二。

方案二:配置NGram分词器(性能最优,适合大数据量)

通过自定义NGram分词器,在索引阶段将文本拆分为固定长度的子串(比如3-5个字符),搜索时直接匹配这些子串,既支持任意位置的模糊匹配,又能保证查询性能。

步骤1:创建带NGram分词器的索引

PUT /your_index_name
{
  "settings": {
    "analysis": {
      "analyzer": {
        "custom_ngram_analyzer": {
          "tokenizer": "custom_ngram_tokenizer",
          "filter": ["lowercase"]
        }
      },
      "tokenizer": {
        "custom_ngram_tokenizer": {
          "type": "ngram",
          "min_gram": 3,
          "max_gram": 5,
          "token_chars": ["letter", "digit"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "custom_ngram_analyzer",
        "search_analyzer": "standard"
      },
      "brand": {
        "type": "text",
        "analyzer": "custom_ngram_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}
  • min_gram: 3和max_gram:5:避免生成过短的token(比如1-2字符),防止匹配大量无关文档;可根据业务调整(比如用户常搜2字符关键词就设为2-4)。
  • search_analyzer: standard:搜索时不对查询词做NGram拆分,直接用原词匹配索引中的NGram子串(比如搜test会匹配索引中tes/est等子串)。

步骤2:使用Multi_match查询

{
  "query": {
    "multi_match": {
      "query": "test",
      "fields": ["brand", "name"]
    }
  }
}

这种方式查询性能远优于wildcard,且能精准匹配包含test的文档,不会返回无关结果。

注意事项

  • 如果已有存量数据,修改索引映射后需要重新索引数据才能生效。
  • 若需要支持更短的关键词匹配(比如2字符),可调整min_gram为2,但需测试是否会出现过多无关匹配。

内容的提问来源于stack exchange,提问作者psilocybin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 08:15:45