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

Spring Boot+JPA+Elasticsearch实现*与?通配符匹配查询

解决方案:Spring Boot 3 Elasticsearch 实现*和?通配符匹配

核心问题分析

你的?通配符失效,大概率是因为依赖Spring Data的派生查询(如findByCodeLike)时,框架对通配符的处理逻辑有限,仅支持*而未正确解析?。Elasticsearch原生支持*(匹配任意长度字符)和?(匹配单个任意字符)的通配符查询,只需调整查询实现方式即可解决。

方案1:手动构建Wildcard查询(推荐,灵活可控)

直接使用Elasticsearch的WildcardQueryBuilder构建查询,绕过Spring Data派生查询的限制,直接传递通配符参数。

代码实现(基于ElasticsearchRestTemplate)

import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class CodeService {

    private final ElasticsearchRestTemplate esRestTemplate;

    // 构造注入
    public CodeService(ElasticsearchRestTemplate esRestTemplate) {
        this.esRestTemplate = esRestTemplate;
    }

    public List<CodeEntity> searchCodeByPattern(String pattern) {
        // 构建原生查询,直接使用传入的*和?通配符
        var searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.wildcardQuery("code", pattern))
                .withPageable(PageRequest.of(0, 100)) // 限制返回前100条
                .build();

        SearchHits<CodeEntity> hits = esRestTemplate.search(searchQuery, CodeEntity.class);
        return hits.stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
    }
}

方案2:Repository层使用@Query注解

在自定义Repository中通过原生Elasticsearch查询语句实现通配符支持,适合希望保留Repository风格的场景。

Repository代码

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface CodeRepository extends ElasticsearchRepository<CodeEntity, String> {

    // 原生Wildcard查询,?0对应第一个参数
    @Query("{\"wildcard\": {\"code\": {\"value\": \"?0\"}}}")
    Page<CodeEntity> findByCodePattern(String pattern, Pageable pageable);
}

Service调用代码

import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class CodeService {

    private final CodeRepository codeRepository;

    public CodeService(CodeRepository codeRepository) {
        this.codeRepository = codeRepository;
    }

    public List<CodeEntity> searchCodeByPattern(String pattern) {
        // 传入分页参数,取第0页的100条数据
        return codeRepository.findByCodePattern(pattern, PageRequest.of(0, 100)).getContent();
    }
}

关键配置:确保字段为Keyword类型

通配符查询对字段类型敏感,如果code字段是text类型且开启了分词,查询结果会不符合预期。必须在实体类中指定code为Keyword类型:

import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Document(indexName = "codes")
public class CodeEntity {

    private String id;

    @Field(type = FieldType.Keyword) // 必须设置为Keyword,避免分词干扰
    private String code;

    // Getter、Setter省略
}

注意事项

  • 通配符放在字符串开头(如*AA)会导致Elasticsearch无法使用索引,查询性能大幅下降,建议业务上引导用户将通配符放在末尾。
  • 如果需要更复杂的模糊匹配,也可以考虑使用regexpQuery,但性能比wildcard更差,需谨慎使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:16:30