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

将可用Elasticsearch查询转Java实现时遇编译错误求解决方案

解决Spring Data Elasticsearch @Query注解编译错误及正确实现

问题场景

有一段可在Kibana正常运行的Elasticsearch查询,尝试通过Spring Data Elasticsearch Repository的@Query注解转换为Java代码时,编译阶段报错:

Error:  Reason: No property searchLocationOnLevel found for type LocationSearch!; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property searchLocationOnLevel found for type LocationSearch!

原Elasticsearch查询语句

GET dev_skp_location/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "regexp": { "name": ".*pur*" }
        },
        {
          "nested": {
            "path": "locationType",
            "query": {
              "bool": {
                "must": [
                  { 
                    "match": { "locationType.level": "1" } 
                  }
                ]
              }
            },
            "score_mode": "avg"
          }
        }
      ]
    }
  }
}

用户尝试的错误代码

@Query("{\n" +
        "     \"bool\":{\n" +
        "        \"must\":[\n" +
        "        {\n" +
        "          \"regexp\": { \"name\": \"\\.*pur\\*\"}\n" +
        "        },\n" +
        "        {\n" +
        "          \"nested\": {\n" +
        "          \"path\": \"locationType\",\n" +
        "          \"query\": {\n" +
        "            \"bool\": {\n" +
        "              \"must\": [\n" +
        "                { \n" +
        "                  \"match\": { \"locationType.level\": \"1\" } \n" +
        "                  \n" +
        "                }]\n" +
        "              }\n" +
        "            },\n" +
        "          \"score_mode\": \"avg\"\n" +
        "        }\n" +
        "      }\n" +
        "    ]\n" +
        "  }\n" +
        " }")
Page<LocationSearch> searchLocationOnLevel(String loc, String level, Pageable pageable);

错误原因分析

  1. Repository父接口错误:如果Repository继承的是JpaRepository而非ElasticsearchRepository,Spring会按JPA规则解析方法名,导致找不到对应属性的错误。
  2. 参数未占位:方法定义了loc和level参数,但查询语句中硬编码了值,未使用参数占位符。
  3. JSON语法错误:原查询的JSON存在括号闭合问题,且Java字符串中的转义字符处理不当。
  4. Regexp写法问题:原ES查询的.*pur*语义是匹配任意字符+pu后接0个或多个r,若要匹配包含pur的字符串,应改为.*pur.*。

正确实现方式

1. 确保Repository继承正确的父接口

Repository必须继承ElasticsearchRepository,而非JPA相关接口:

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 LocationSearchRepository extends ElasticsearchRepository<LocationSearch, String> {
    // 方法定义
}

2. 修正@Query语句(位置参数版)

使用?0、?1对应方法的第1、第2个参数,同时修正JSON语法和转义:

@Query("{\n" +
        "  \"query\": {\n" +
        "    \"bool\": {\n" +
        "      \"must\": [\n" +
        "        {\n" +
        "          \"regexp\": { \"name\": \"?0\" }\n" +
        "        },\n" +
        "        {\n" +
        "          \"nested\": {\n" +
        "            \"path\": \"locationType\",\n" +
        "            \"query\": {\n" +
        "              \"bool\": {\n" +
        "                \"must\": [\n" +
        "                  {\n" +
        "                    \"match\": { \"locationType.level\": \"?1\" }\n" +
        "                  }\n" +
                "                ]\n" +
        "              }\n" +
        "            },\n" +
        "            \"score_mode\": \"avg\"\n" +
        "          }\n" +
        "        }\n" +
        "      ]\n" +
        "    }\n" +
        "  }\n" +
        "}")
Page<LocationSearch> searchLocationOnLevel(String locPattern, String level, Pageable pageable);

3. 修正@Query语句(命名参数版)

若使用命名参数,需配合@Param注解,可读性更强:

import org.springframework.data.repository.query.Param;

// ...

@Query("{\n" +
        "  \"query\": {\n" +
        "    \"bool\": {\n" +
        "      \"must\": [\n" +
        "        {\n" +
        "          \"regexp\": { \"name\": \":locPattern\" }\n" +
        "        },\n" +
        "        {\n" +
        "          \"nested\": {\n" +
        "            \"path\": \"locationType\",\n" +
        "            \"query\": {\n" +
        "              \"bool\": {\n" +
        "                \"must\": [\n" +
        "                  {\n" +
        "                    \"match\": { \"locationType.level\": \":level\" }\n" +
        "                  }\n" +
                "                ]\n" +
        "              }\n" +
        "            },\n" +
        "            \"score_mode\": \"avg\"\n" +
        "          }\n" +
        "        }\n" +
        "      ]\n" +
        "    }\n" +
        "  }\n" +
        "}")
Page<LocationSearch> searchLocationOnLevel(@Param("locPattern") String locPattern, @Param("level") String level, Pageable pageable);

4. 确保实体类映射正确

LocationSearch实体类需正确映射ES索引,嵌套字段locationType需标注@Nested注解:

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

@Document(indexName = "dev_skp_location")
public class LocationSearch {
    private String id;
    
    @Field(type = FieldType.Text)
    private String name;
    
    @Nested
    private LocationType locationType;
    
    // getter、setter方法
}

class LocationType {
    @Field(type = FieldType.Keyword)
    private String level;
    
    // 其他字段及getter、setter
}

5. 方法调用示例

若要匹配包含pur的名称和level为1的记录,调用时传入正确的正则表达式:

Page<LocationSearch> result = locationSearchRepository.searchLocationOnLevel(".*pur.*", "1", PageRequest.of(0, 10));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:05:21