Prevent BigInteger serialization errors in term queries (#57987)

When a numeric value in e.g. a `term` query doesn't fit into a long, it
curerently gets parsed to a BigInteger object, that the various term query
builders store untouched. This leads to serialization errors when these queries
are sent across the wire. Instead we can convert to a string representation
early on, since that is what we store e.g. when indexing big integers into
`keyword` fields anyway.

Closes #57917
This commit is contained in:
Christoph Büscher 2020-06-18 10:38:14 +02:00
parent f3b6e41f02
commit 31d8e03954
3 changed files with 38 additions and 0 deletions

View File

@ -23,11 +23,15 @@ import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.rescore.QueryRescorerBuilder;
import org.elasticsearch.search.sort.SortOrder;
@ -427,6 +431,24 @@ public class SimpleSearchIT extends ESIntegTestCase {
}
}
public void testTermQueryBigInt() throws Exception {
prepareCreate("idx").setMapping("field", "type=keyword").get();
ensureGreen("idx");
client().prepareIndex("idx")
.setId("1")
.setSource("{\"field\" : 80315953321748200608 }", XContentType.JSON)
.setRefreshPolicy(RefreshPolicy.IMMEDIATE)
.get();
String queryJson = "{ \"field\" : { \"value\" : 80315953321748200608 } }";
XContentParser parser = createParser(JsonXContent.jsonXContent, queryJson);
parser.nextToken();
TermQueryBuilder query = TermQueryBuilder.fromXContent(parser);
SearchResponse searchResponse = client().prepareSearch("idx").setQuery(query).get();
assertEquals(1, searchResponse.getHits().getTotalHits().value);
}
public void testTooLongRegexInRegexpQuery() throws Exception {
createIndex("idx");
indexRandom(true, client().prepareIndex("idx", "type").setSource("{}", XContentType.JSON));

View File

@ -39,6 +39,7 @@ import org.elasticsearch.common.xcontent.XContentLocation;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Collection;
@ -204,6 +205,8 @@ public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder<QB>>
return BytesRefs.toBytesRef(obj);
} else if (obj instanceof CharBuffer) {
return new BytesRef((CharBuffer) obj);
} else if (obj instanceof BigInteger) {
return BytesRefs.toBytesRef(obj);
}
return obj;
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.PointRangeQuery;
@ -166,6 +167,18 @@ public class TermQueryBuilderTests extends AbstractTermQueryTestCase<TermQueryBu
assertEquals("[term] query doesn't support multiple fields, found [message1] and [message2]", e.getMessage());
}
public void testParseAndSerializeBigInteger() throws IOException {
String json = "{\n" +
" \"term\" : {\n" +
" \"foo\" : {\n" +
" \"value\" : 80315953321748200608\n" +
" }\n" +
" }\n" +
"}";
QueryBuilder parsedQuery = parseQuery(json);
assertSerialization(parsedQuery);
}
public void testTypeField() throws IOException {
TermQueryBuilder builder = QueryBuilders.termQuery("_type", "value1");
builder.doToQuery(createShardContext());