|
@@ -61,6 +61,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|
|
import org.elasticsearch.index.mapper.MapperService;
|
|
|
import org.elasticsearch.index.search.QueryStringQueryParser;
|
|
|
import org.elasticsearch.search.internal.SearchContext;
|
|
|
+import org.elasticsearch.test.AbstractQueryTestCase;
|
|
|
import org.hamcrest.CoreMatchers;
|
|
|
import org.hamcrest.Matchers;
|
|
|
|
|
@@ -71,6 +72,7 @@ import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
+import java.util.Locale;
|
|
|
import java.util.Map;
|
|
|
|
|
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
|
@@ -83,12 +85,7 @@ import static org.hamcrest.CoreMatchers.hasItems;
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
import static org.hamcrest.Matchers.instanceOf;
|
|
|
|
|
|
-public class QueryStringQueryBuilderTests extends FullTextQueryTestCase<QueryStringQueryBuilder> {
|
|
|
- @Override
|
|
|
- protected boolean isCacheable(QueryStringQueryBuilder queryBuilder) {
|
|
|
- return queryBuilder.fuzziness() != null
|
|
|
- || isCacheable(queryBuilder.fields().keySet(), queryBuilder.queryString());
|
|
|
- }
|
|
|
+public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStringQueryBuilder> {
|
|
|
|
|
|
@Override
|
|
|
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
|
|
@@ -108,8 +105,11 @@ public class QueryStringQueryBuilderTests extends FullTextQueryTestCase<QueryStr
|
|
|
int numTerms = randomIntBetween(0, 5);
|
|
|
String query = "";
|
|
|
for (int i = 0; i < numTerms; i++) {
|
|
|
- //min length 4 makes sure that the text is not an operator (AND/OR) so toQuery won't break
|
|
|
- query += (randomBoolean() ? STRING_FIELD_NAME + ":" : "") + randomAlphaOfLengthBetween(4, 10) + " ";
|
|
|
+ // min length 4 makes sure that the text is not an operator (AND/OR) so toQuery won't break
|
|
|
+ // also avoid "now" since we might hit dqte fields later and this complicates caching checks
|
|
|
+ String term = randomValueOtherThanMany(s -> s.toLowerCase(Locale.ROOT).contains("now"),
|
|
|
+ () -> randomAlphaOfLengthBetween(4, 10));
|
|
|
+ query += (randomBoolean() ? STRING_FIELD_NAME + ":" : "") + term + " ";
|
|
|
}
|
|
|
QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(query);
|
|
|
if (randomBoolean()) {
|
|
@@ -1578,4 +1578,39 @@ public class QueryStringQueryBuilderTests extends FullTextQueryTestCase<QueryStr
|
|
|
assertThat(disjunctionMaxQuery.getDisjuncts(), hasItems(new TermQuery(new Term(STRING_FIELD_NAME, "hello")),
|
|
|
new TermQuery(new Term(STRING_FIELD_NAME_2, "hello"))));
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Query terms that contain "now" can trigger a query to not be cacheable.
|
|
|
+ * This test checks the search context cacheable flag is updated accordingly.
|
|
|
+ */
|
|
|
+ public void testCachingStrategiesWithNow() throws IOException {
|
|
|
+ // if we hit all fields, this should contain a date field and should diable cachability
|
|
|
+ String query = "now " + randomAlphaOfLengthBetween(4, 10);
|
|
|
+ QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(query);
|
|
|
+ assertQueryCachability(queryStringQueryBuilder, false);
|
|
|
+
|
|
|
+ // if we hit a date field with "now", this should diable cachability
|
|
|
+ queryStringQueryBuilder = new QueryStringQueryBuilder("now");
|
|
|
+ queryStringQueryBuilder.field(DATE_FIELD_NAME);
|
|
|
+ assertQueryCachability(queryStringQueryBuilder, false);
|
|
|
+
|
|
|
+ // everything else is fine on all fields
|
|
|
+ query = randomFrom("NoW", "nOw", "NOW") + " " + randomAlphaOfLengthBetween(4, 10);
|
|
|
+ queryStringQueryBuilder = new QueryStringQueryBuilder(query);
|
|
|
+ assertQueryCachability(queryStringQueryBuilder, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertQueryCachability(QueryStringQueryBuilder qb, boolean cachingExpected) throws IOException {
|
|
|
+ QueryShardContext context = createShardContext();
|
|
|
+ assert context.isCacheable();
|
|
|
+ /*
|
|
|
+ * We use a private rewrite context here since we want the most realistic way of asserting that we are cacheable or not. We do it
|
|
|
+ * this way in SearchService where we first rewrite the query with a private context, then reset the context and then build the
|
|
|
+ * actual lucene query
|
|
|
+ */
|
|
|
+ QueryBuilder rewritten = rewriteQuery(qb, new QueryShardContext(context));
|
|
|
+ assertNotNull(rewritten.toQuery(context));
|
|
|
+ assertEquals("query should " + (cachingExpected ? "" : "not") + " be cacheable: " + qb.toString(), cachingExpected,
|
|
|
+ context.isCacheable());
|
|
|
+ }
|
|
|
}
|