如何从ElasticSearch查询结果中过滤全部指定邮箱?
问题描述
当前基于Hibernate Search的Elasticsearch查询仅能过滤filterEmailArray数组的第0个邮箱元素,需修改代码实现过滤数组内全部指定邮箱。
相关现有代码如下:
邮箱精确匹配分析器配置
context.analyzer("email_indexing_exact") .custom() .tokenizer("uax_url_email");
当前查询代码
SearchSession searchSession = Search.session(entityManager); String[] fieldsArray = {"displayName", "email"}; String[] filterEmailArray = filterEmail.split(","); var query = searchSession.search(User.class) .extension(ElasticsearchExtension.get()) .select(ElasticsearchSearchProjectionFactory::source) .where(f -> f.bool() .must(f.match().fields(fieldsArray).matching(word).analyzer("autocomplete_search")) .mustNot(f.match().field("email").matching(filterEmailArray[0]).analyzer("email_indexing_exact")) ) .sort(f -> f.score().desc());
修改方案
提供两种可行修改方式,均能实现过滤数组内所有指定邮箱:
方式一:使用Terms查询(推荐)
Terms查询专为匹配字段值在指定集合的场景设计,搭配精确分析器可实现高效精准过滤:
SearchSession searchSession = Search.session(entityManager); String[] fieldsArray = {"displayName", "email"}; String[] filterEmailArray = filterEmail.split(","); var query = searchSession.search(User.class) .extension(ElasticsearchExtension.get()) .select(ElasticsearchSearchProjectionFactory::source) .where(f -> f.bool() .must(f.match().fields(fieldsArray).matching(word).analyzer("autocomplete_search")) // 替换单个match为terms查询,传入整个邮箱数组 .mustNot(f.terms().field("email").matching(filterEmailArray).analyzer("email_indexing_exact")) ) .sort(f -> f.score().desc());
方式二:遍历数组构建多条件MustNot查询
如果需要更灵活的条件组合逻辑,可遍历邮箱数组逐个添加过滤条件:
SearchSession searchSession = Search.session(entityManager); String[] fieldsArray = {"displayName", "email"}; String[] filterEmailArray = filterEmail.split(","); // 先构建基础布尔查询 var boolQuery = f.bool() .must(f.match().fields(fieldsArray).matching(word).analyzer("autocomplete_search")); // 遍历所有需过滤的邮箱,添加到mustNot条件中 for (String excludeEmail : filterEmailArray) { boolQuery.mustNot(f.match().field("email").matching(excludeEmail).analyzer("email_indexing_exact")); } var query = searchSession.search(User.class) .extension(ElasticsearchExtension.get()) .select(ElasticsearchSearchProjectionFactory::source) .where(boolQuery) .sort(f -> f.score().desc());
补充说明
- 方式一的Terms查询性能更优,Elasticsearch会批量处理所有匹配值,比多个独立Match查询的组合效率更高。
- 两种方式均保留了
email_indexing_exact分析器,确保邮箱字符串被精确匹配,避免分词逻辑导致的误过滤。
内容的提问来源于stack exchange,提问作者Umut Emre Önder
相关产品推荐
相关产品推荐

