Elasticsearch 8.6 中使用 Spring Boot 2.7.15 的通配符动态查询

问题描述 投票:0回答:1
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

型号:

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Map;

@Data
@Document(indexName = "content")
public class Content {
    @Id
    private String id;
    private Long docTypeId;
    @Field(type = FieldType.Nested, includeInParent = true)
    private Map<String, Object> data;
}

内容存储库:

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ContentRepository extends ElasticsearchRepository<Content, String> {
}

内容服务:

import lombok.RequiredArgsConstructor;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class ContentService {
    private final ContentRepository contentRepository;
    private final ElasticsearchOperations elasticsearchOperations;

    public Page<Content> getContentsByQueryParams(Map<String, String> requestParams, int page, int size) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        for (Map.Entry<String, String> entry : requestParams.entrySet()) {
            String field = "data." + entry.getKey();
            String value = entry.getValue();

            boolQueryBuilder.must(QueryBuilders.nestedQuery(field,
                    QueryBuilders.termQuery(field, value), ScoreMode.None));
        }

        Pageable pageable = PageRequest.of(page, size);

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageable)
                .build();

        SearchHits<Content> searchHits = elasticsearchOperations.search(searchQuery, Content.class);
        long totalHits = searchHits.getTotalHits();
        List<SearchHit<Content>> hits = searchHits.getSearchHits();
        List<Content> contentList = hits.stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());

        return new PageImpl<>(contentList, pageable, totalHits);
    }
}

内容控制器:

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/contents")
public class ContentController {
    private final ContentService contentService;
    @Value("${searchservice.default-page-size}")
    private Integer defaultPageSize;

    @GetMapping
    public ResponseEntity<Page<Content>> findAllContents(@RequestParam Map<String, String> requestParams) {
        String pageObj = requestParams.remove("page");
        String sizeObj = requestParams.remove("size");
        int page = (pageObj == null ? 0 : Integer.parseInt(pageObj));
        int size = (sizeObj == null ? defaultPageSize : Integer.parseInt(sizeObj));
        return ResponseEntity.ok(contentService.getContentsByQueryParams(requestParams, page, size));
    }
}

样本数据 - 类型 1:

{
    "docTypeId": 1,
    "data": {
        "code": "32145kj324",
        "name": "ownership document",
        "field1": {
            "province": "NY",
            "country": "USA",
            "mainno": 2395
        },
        "ownerprop": {
            "name": "xxx",
            "family": "yyy",
            "nationalid": "123456789"
        },
        "gis": {
            "latitude": 11.568914135,
            "longitude": 22.254526558
        }
    }
}

样本数据 - 类型 2:

{
    "docTypeId": 2,
    "data": {
        "code": "32145kj324",
        "name": "ownership document",
        "ownerprop": {
            "name": "xxx",
            "family": "yyy",
            "nationalid": "123456789"
        },
        "gis": {
            "latitude": 11.568914135,
            "longitude": 22.254526558,
            "field1": {
                "province": "NY",
                "country": "USA",
                "mainno": 2395
            }
        }
    }
}

网址端点:

获取http://localhost:8080/api/v1/contents?province=NY&country=USA

预期结果:

返回两种带分页的样本类型

实际结果:

回应:

{ "时间戳": "2023-09-24T11:58:10.589+00:00", “状态”:500, "error": "内部服务器错误", “路径”:“/api/v1/内容” }

错误:

2023-09-24 13:42:46,814 错误 [http-nio-8095-exec-1] org.apache.juli.logging.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] 在路径 [] 的上下文中抛出异常【请求处理失败;嵌套异常是 java.lang.IllegalArgumentException: 未处理的查询实现 org.springframework.data.elasticsearch.core.query.NativeSearchQuery] 其根本原因 java.lang.IllegalArgumentException:未处理的查询实现org.springframework.data.elasticsearch.core.query.NativeSearchQuery 在 org.springframework.data.elasticsearch.client.elc.RequestConverter.getQuery(RequestConverter.java:1346) 在 org.springframework.data.elasticsearch.client.elc.RequestConverter.searchRequest(RequestConverter.java:1052) 在 org.springframework.data.elasticsearch.client.elc.RequestConverter.searchRequest(RequestConverter.java:1033) 在 org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.search(ElasticsearchTemplate.java:311) 在 org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate.search(AbstractElasticsearchTemplate.java:418) 在 com.example.searchservice.service.ContentService.getContentsByQueryParams(ContentService.java:69) 在 com.example.searchservice.controller.ContentController.findAllContents(ContentController.java:52) ...

spring-boot elasticsearch spring-data-elasticsearch
1个回答
0
投票

您正在使用

NativeSearchQuery
,它是 Spring Data Elasticsearch 实现中的一个类,使用 Elasticsearch 中旧的已弃用的
RestHighLevelClient
; Spring Data Elasticsearch 4.4 版之前一直使用它作为默认值。

您的堆栈跟踪显示您正在使用的实际实现是使用新的

ElasticsearchClient
的实现,这显示在包
org.springframework.data.elasticsearch.client.elc
中。对于此客户端,您需要使用
NativeQuery

所以你的设置似乎有些混乱。

© www.soinside.com 2019 - 2024. All rights reserved.