Between 7.9.3 and 7.12.1 it seems the way that arguments to termsQuery() are serialized have changed. In 7.9.3 it used my XContentBuilderExtension to convert my classes to strings that could be understood by elasticsearch.
But now in 7.12.1, it goes through StreamOutput which does not seem to have a way to add any customization, so it fails to serialize.
Is there a way to get it to serialize my classes correctly, or do I just have to manually serialize everything before passing it to query builders now?
I believe this issue was created by this pull request:
elastic:master
← gf2121:terms_query_optmize
opened 04:32PM - 10 Jan 21 UTC
#67132 tried to cache all the results of serialization of `SearchSourceBuilder`,… which is invasive. So this is a patch that only aims to optimizing `TermsQueryBuilder`.
Here are some benchmark results (indices and queries are the same as #67132):
**No Param**
target | baseline | candidate
-- | -- | --
1 index (8 shards) | 83ms | 13ms
30 indices (240 shards) | 2935ms | 201ms
**set pre_filter_shard_size=240**
target | baseline | candidate
-- | -- | --
1 index (8 shards) | 81ms | 13ms
30 indices (240 shards) | 731ms | 104ms
Which has spawned these two related issues:
opened 06:57AM - 31 May 21 UTC
closed 01:33PM - 31 May 21 UTC
:Search/Search
>bug
Team:Search
v7.12.0
v7.13.0
v8.0.0
**Elasticsearch version**: 7.12.1
**Description of the problem including expe… cted versus actual behavior**:
Prior to Elasticsearch 7.12.0 using terms query with an enum value was working without any issues. After upgrading java Elasticsearch client from 7.10.0 to 7.12.1 the following exception has been thrown when terms query is used for an Enum value. The same code is tested for previous versions and it works without any issues.
```
BoolQueryBuilder query = QueryBuilders.boolQuery();
query.mustNot(QueryBuilders.termsQuery("foo", Thing.BAR));
public Enum Thing{
FOO, BAR;
@Override
@JsonValue
public String toString() {
return name().toLowerCase();
}
}
```
**Exception:**
```
Caused by: java.lang.IllegalArgumentException: can not write type [class com.example.Thing]
at org.elasticsearch.common.io.stream.StreamOutput.writeGenericValue(StreamOutput.java:845)
at org.elasticsearch.common.io.stream.StreamOutput.lambda$static$12(StreamOutput.java:700)
at org.elasticsearch.common.io.stream.StreamOutput.writeGenericValue(StreamOutput.java:843)
at org.elasticsearch.index.query.TermsQueryBuilder$Values.serialize(TermsQueryBuilder.java:434)
at org.elasticsearch.index.query.TermsQueryBuilder$BinaryValues.<init>(TermsQueryBuilder.java:493)
at org.elasticsearch.index.query.TermsQueryBuilder$BinaryValues.<init>(TermsQueryBuilder.java:483)
at org.elasticsearch.index.query.TermsQueryBuilder.<init>(TermsQueryBuilder.java:161)
at org.elasticsearch.index.query.TermsQueryBuilder.<init>(TermsQueryBuilder.java:141)
at org.elasticsearch.index.query.QueryBuilders.termsQuery(QueryBuilders.java:568)
```
Prior to 7.12.0, the same code snippet works without any issues. The workaround is to use .toString() wherever an Enum value has been used.
After exploring what could have gone wrong in the version 7.12.1 client, we realised that [this PR](https://github.com/elastic/elasticsearch/pull/67223) has created the mentioned side effect. The issue seems to be related to line 168 of TermsQueryBuilder.java.
opened 05:49PM - 20 Apr 21 UTC
:Search/Search
>enhancement
Team:Search
We currently have a constructor on TermsQueryBuilder that takes generic `Object.… .. values` as argument, probably to
facilitate creating terms queries for things like `Date` and `GeoPoint`. However we need to be able to serialize these objects via our transport
protocol (everything that `StreamOutput.writeGenericValue` seems to work at least on that level), so not all Objects will work.
We [recently changed](https://github.com/elastic/elasticsearch/pull/67223) the code to use this serialization alread on construction to convert values to a BytesReference.
Before that it was possible to use the object ctor for example in the High Level Rest Client for Enums, the json serialization for the request would then convert these to their String representation behind the scenes (see #71388). This doesn't work any longe, which on one hand is a good thing because we fail early on things we later cannot serialize anyway, but also shows how misleading using this constructor can be.
I'm opening this issue as a starting point for investigation if we can make this ctor safer, either by replacing it with a stronger typed one (and deprecate and eventually remove the existing one), or by enhancing javadocs on the ctor to avoid its wider usage except for cases where it really makes sense (i.e. Date, GeoPoint etc...).
Relates to #71388
system
(system)
Closed
July 15, 2021, 9:16pm
2
This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.