<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));
}
}
{
"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
}
}
}
{
"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) ...
您正在使用
NativeSearchQuery
,它是 Spring Data Elasticsearch 实现中的一个类,使用 Elasticsearch 中旧的已弃用的 RestHighLevelClient
; Spring Data Elasticsearch 4.4 版之前一直使用它作为默认值。
您的堆栈跟踪显示您正在使用的实际实现是使用新的
ElasticsearchClient
的实现,这显示在包 org.springframework.data.elasticsearch.client.elc
中。对于此客户端,您需要使用NativeQuery
。
所以你的设置似乎有些混乱。