如何在自定义弹性搜索查询Java中使用术语查询?

时间:2019-03-13 09:50:12

标签: java spring-boot spring-data spring-data-elasticsearch

我想在弹性搜索中针对值数组搜索字段。我正在用Java编写自定义术语查询,但每次都会失败。

代码-

@Query("{ \"bool\" : { \"must\" : [\t{ \"term\" : {\"userId\" : ?0 } },\t{ \"terms\" : { \"language\" : ?1 } } ] } }")
List<PostElastic> findByProviderIdAndLanguagesPostOrderLessThanFromId(Long providerId, List<String> languages, Long fromTimestamp,Pageable pageable);

传递语言字段的任何值时,都会出现以下异常

java.io.IOException: Unrecognized token 'en': was expecting ('true', 'false' or 'null')
at [Source: [B@20502fa2; line: 1, column: 86]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702) ~[jackson-core-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558) ~[jackson-core-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3528) ~[jackson-core-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2686) ~[jackson-core-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:878) ~[jackson-core-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:772) ~[jackson-core-2.9.6.jar:2.9.6]
at org.elasticsearch.common.xcontent.json.JsonXContentParser.nextToken(JsonXContentParser.java:55) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.TermsQueryBuilder.parseValues(TermsQueryBuilder.java:391) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.TermsQueryBuilder.fromXContent(TermsQueryBuilder.java:356) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.SearchModule.lambda$registerQuery$10(SearchModule.java:763) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.common.xcontent.NamedXContentRegistry.parseNamedObject(NamedXContentRegistry.java:143) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.common.xcontent.support.AbstractXContentParser.namedObject(AbstractXContentParser.java:402) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.QueryParseContext.parseInnerQueryBuilder(QueryParseContext.java:122) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.BoolQueryBuilder.fromXContent(BoolQueryBuilder.java:356) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.SearchModule.lambda$registerQuery$10(SearchModule.java:763) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.common.xcontent.NamedXContentRegistry.parseNamedObject(NamedXContentRegistry.java:143) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.common.xcontent.support.AbstractXContentParser.namedObject(AbstractXContentParser.java:402) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.QueryParseContext.parseInnerQueryBuilder(QueryParseContext.java:122) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.WrapperQueryBuilder.doRewrite(WrapperQueryBuilder.java:167) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.index.query.AbstractQueryBuilder.rewrite(AbstractQueryBuilder.java:263) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.builder.SearchSourceBuilder.rewrite(SearchSourceBuilder.java:879) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.internal.ShardSearchLocalRequest.rewrite(ShardSearchLocalRequest.java:244) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.internal.ShardSearchTransportRequest.rewrite(ShardSearchTransportRequest.java:171) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.SearchService.createSearchContext(SearchService.java:530) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.SearchService.createContext(SearchService.java:479) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:461) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.search.SearchService.executeDfsPhase(SearchService.java:226) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.action.search.SearchTransportService$5.messageReceived(SearchTransportService.java:332) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.action.search.SearchTransportService$5.messageReceived(SearchTransportService.java:329) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:69) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.transport.TransportService$7.doRun(TransportService.java:662) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:675) ~[elasticsearch-5.6.10.jar:5.6.10]
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) ~[elasticsearch-5.6.10.jar:5.6.10]
... 3 common frames omitted

我不能使用术语查询,因为数组大小是可变的,因此无法检查每个元素 当我使用邮递员在弹性搜索上直接运行查询时,它会起作用。

我编写任何错误的查询时,都无法在线找到任何来源

1 个答案:

答案 0 :(得分:1)

根据the documentation for the @Query annotation,如果您打算使用String参数,则必须自己添加双引号:

  

示例54。使用@Query注释在方法中声明查询。

public interface BookRepository extends ElasticsearchRepository<Book, String> {
    @Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")
    Page<Book> findByName(String name,Pageable pageable);
}

注意:示例代码无法正确转义引号,我创建了DATAES-546来解决此问题。

这也解释了您收到的错误,因为您实际上是在发送{"language": en}而不是{"language": "en"}。唯一可能的未加引号的值为nulltruefalse(因此出现错误消息)。

您可以使用以下方法解决此问题:

@Query("{ \"bool\" : { \"must\" : [\t{ \"term\" : {\"userId\" : ?0 } },\t{ \"terms\" : { \"language\" : \"?1\" } } ] } }")
List<PostElastic> findByProviderIdAndLanguagesPostOrderLessThanFromId(Long providerId, List<String> languages, Long fromTimestamp,Pageable pageable);