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

Spring整合Elasticsearch实现不区分大小写搜索方案咨询

解决Elasticsearch不区分大小写搜索问题

问题根源

搜索区分大小写通常和字段的映射类型、分词器/归一化器配置直接相关:

  • 如果字段是keyword类型且未配置小写归一化,ES会精确匹配大小写;
  • 如果text类型字段使用了不包含小写转换的分词器(如whitespace),也会导致大小写敏感;
  • 你的代码还存在逻辑问题:当categoryName存在时,会直接替换掉之前的多字段查询,导致原有搜索条件失效。

解决方案

1. 修复代码中的查询逻辑错误

当前代码中,withQuery会覆盖之前的查询条件,需要用BoolQuery组合多字段查询和分类查询:

// 构建多字段匹配查询
MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(criteria)
        .field("displayName")
        .field("authorName")
        .field("description")
        .field("shortDescription")
        .field("tag")
        .field("translatedMetadataList")
        .field("name")
        .field("packageName")
        .type(MultiMatchQueryBuilder.Type.PHRASE_PREFIX);

// 用BoolQuery组合条件
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().must(multiMatchQuery);
if(categoryName.isPresent()) {
    // 注意:如果是嵌套字段category.name,需要写"category.name"
    boolQuery.must(QueryBuilders.matchQuery("category.name", categoryName.get()));
}

NativeSearchQueryBuilder nativeSearch = new NativeSearchQueryBuilder()
        .withQuery(boolQuery)
        .withPageable(PageRequest.of(page, size));

SearchQuery searchQuery = nativeSearch.build();
Page<Game> gameList = gameRepo.search(searchQuery);

2. 针对字段映射的优化(核心解决大小写问题)

根据字段类型不同,选择对应的方案:

方案A:处理keyword类型字段(无需重建索引)

如果目标字段是keyword类型(比如packageName),可以添加小写归一化器(normalizer),让存储和查询时自动转为小写:

  1. 更新索引的settings,添加自定义归一化器:
PUT /your_game_index/_settings
{
  "analysis": {
    "normalizer": {
      "lowercase_normalizer": {
        "type": "custom",
        "filter": ["lowercase"]
      }
    }
  }
}
  1. 更新字段的映射,应用归一化器:
PUT /your_game_index/_mapping
{
  "properties": {
    "packageName": {
      "type": "keyword",
      "normalizer": "lowercase_normalizer"
    },
    // 其他需要处理的keyword字段同理
    "tag": {
      "type": "keyword",
      "normalizer": "lowercase_normalizer"
    }
  }
}
  1. 重新索引已有数据(让归一化器生效):
POST _reindex
{
  "source": {
    "index": "your_game_index"
  },
  "dest": {
    "index": "your_game_index"
  }
}

方案B:处理text类型字段(需重建索引,适合字段未配置正确分词器)

如果目标字段是text类型,但分词器未包含小写转换(比如自定义分词器),需要重建索引并配置正确的分词器:

  1. 创建新索引,配置带小写过滤的分词器(默认standard分词器已包含小写转换,若需自定义可参考):
PUT /your_game_index_new
{
  "settings": {
    "analysis": {
      "analyzer": {
        "lowercase_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "displayName": {
        "type": "text",
        "analyzer": "lowercase_analyzer"
      },
      // 其他text字段同理配置
      "authorName": {
        "type": "text",
        "analyzer": "lowercase_analyzer"
      },
      // 保留原有嵌套字段映射
      "category": {
        "type": "nested",
        "include_in_parent": true,
        "properties": {
          "description": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "id": {"type": "long"},
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}
  1. 迁移数据到新索引:
POST _reindex
{
  "source": {
    "index": "your_game_index"
  },
  "dest": {
    "index": "your_game_index_new"
  }
}
  1. 切换索引别名(避免修改应用代码):
POST /_aliases
{
  "actions": [
    {"remove": {"index": "your_game_index", "alias": "your_game_index_alias"}},
    {"add": {"index": "your_game_index_new", "alias": "your_game_index_alias"}}
  ]
}

之后应用中使用别名your_game_index_alias即可。

方案C:临时查询层面处理(仅应急用)

如果无法修改映射或重建索引,可临时将搜索条件转为小写:

MultiMatchQueryBuilder qb = QueryBuilders.multiMatchQuery(criteria.toLowerCase())
        // 字段列表不变
        .field("displayName")
        ...;

注意:该方法仅当字段存储的内容已被转为小写时有效(比如text字段用standard分词器),如果是keyword字段存储大写内容,此方法无法匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:35:57