Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow overriding all-field leniency when lenient option is specified #21504

Merged
merged 1 commit into from
Nov 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -964,8 +964,8 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
this.fieldsAndWeights.size() == 0)) {
// Use the automatically determined expansion of all queryable fields
resolvedFields = allQueryableDefaultFields(context);
// Automatically set leniency to "true" so mismatched fields don't cause exceptions
qpSettings.lenient(true);
// Automatically set leniency to "true" if unset so mismatched fields don't cause exceptions
qpSettings.lenient(lenient == null ? true : lenient);
} else {
qpSettings.defaultField(this.defaultField == null ? context.defaultField() : this.defaultField);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
private int flags = DEFAULT_FLAGS;
/** Flag specifying whether query should be forced to expand to all searchable fields */
private Boolean useAllFields;
/** Whether or not the lenient flag has been set or not */
private boolean lenientSet = false;

/** Further search settings needed by the ES specific query string parser only. */
private Settings settings = new Settings();
Expand Down Expand Up @@ -162,6 +164,9 @@ public SimpleQueryStringBuilder(StreamInput in) throws IOException {
in.readBoolean(); // lowercase_expanded_terms
}
settings.lenient(in.readBoolean());
if (in.getVersion().onOrAfter(V_5_1_0_UNRELEASED)) {
this.lenientSet = in.readBoolean();
}
settings.analyzeWildcard(in.readBoolean());
if (in.getVersion().before(V_5_1_0_UNRELEASED)) {
in.readString(); // locale
Expand All @@ -188,6 +193,9 @@ protected void doWriteTo(StreamOutput out) throws IOException {
out.writeBoolean(true); // lowercase_expanded_terms
}
out.writeBoolean(settings.lenient());
if (out.getVersion().onOrAfter(V_5_1_0_UNRELEASED)) {
out.writeBoolean(lenientSet);
}
out.writeBoolean(settings.analyzeWildcard());
if (out.getVersion().before(V_5_1_0_UNRELEASED)) {
out.writeString(Locale.ROOT.toLanguageTag()); // locale
Expand Down Expand Up @@ -315,6 +323,7 @@ public String quoteFieldSuffix() {
/** Specifies whether query parsing should be lenient. Defaults to false. */
public SimpleQueryStringBuilder lenient(boolean lenient) {
this.settings.lenient(lenient);
this.lenientSet = true;
return this;
}

Expand Down Expand Up @@ -372,7 +381,7 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
this.fieldsAndWeights.isEmpty())) {
resolvedFieldsAndWeights = QueryStringQueryBuilder.allQueryableDefaultFields(context);
// Need to use lenient mode when using "all-mode" so exceptions aren't thrown due to mismatched types
newSettings.lenient(true);
newSettings.lenient(lenientSet ? settings.lenient() : true);
} else {
// Use the default field if no fields specified
if (fieldsAndWeights.isEmpty()) {
Expand Down Expand Up @@ -444,7 +453,9 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep

builder.field(FLAGS_FIELD.getPreferredName(), flags);
builder.field(DEFAULT_OPERATOR_FIELD.getPreferredName(), defaultOperator.name().toLowerCase(Locale.ROOT));
builder.field(LENIENT_FIELD.getPreferredName(), settings.lenient());
if (lenientSet) {
builder.field(LENIENT_FIELD.getPreferredName(), settings.lenient());
}
builder.field(ANALYZE_WILDCARD_FIELD.getPreferredName(), settings.analyzeWildcard());
if (settings.quoteFieldSuffix() != null) {
builder.field(QUOTE_FIELD_SUFFIX_FIELD.getPreferredName(), settings.quoteFieldSuffix());
Expand Down Expand Up @@ -473,7 +484,7 @@ public static Optional<SimpleQueryStringBuilder> fromXContent(QueryParseContext
Operator defaultOperator = null;
String analyzerName = null;
int flags = SimpleQueryStringFlag.ALL.value();
boolean lenient = SimpleQueryStringBuilder.DEFAULT_LENIENT;
Boolean lenient = null;
boolean analyzeWildcard = SimpleQueryStringBuilder.DEFAULT_ANALYZE_WILDCARD;
String quoteFieldSuffix = null;
Boolean useAllFields = null;
Expand Down Expand Up @@ -565,7 +576,10 @@ public static Optional<SimpleQueryStringBuilder> fromXContent(QueryParseContext
SimpleQueryStringBuilder qb = new SimpleQueryStringBuilder(queryBody);
qb.boost(boost).fields(fieldsAndWeights).analyzer(analyzerName).queryName(queryName).minimumShouldMatch(minimumShouldMatch);
qb.flags(flags).defaultOperator(defaultOperator);
qb.lenient(lenient).analyzeWildcard(analyzeWildcard).boost(boost).quoteFieldSuffix(quoteFieldSuffix);
if (lenient != null) {
qb.lenient(lenient);
}
qb.analyzeWildcard(analyzeWildcard).boost(boost).quoteFieldSuffix(quoteFieldSuffix);
qb.useAllFields(useAllFields);
return Optional.of(qb);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ public void testBooleanStrictQuery() throws Exception {
containsString("Can't parse boolean value [foo], expected [true] or [false]"));
}

public void testAllFieldsWithSpecifiedLeniency() throws IOException {
Exception e = expectThrows(Exception.class, () ->
client().prepareSearch("test").setQuery(
queryStringQuery("f_date:[now-2D TO now]").lenient(false)).get());
assertThat(ExceptionsHelper.detailedMessage(e),
containsString("unit [D] not supported for date math [-2D]"));
}

private void assertHits(SearchHits hits, String... ids) {
assertThat(hits.totalHits(), equalTo((long) ids.length));
Set<String> hitIds = new HashSet<>();
Expand All @@ -263,5 +271,4 @@ private void assertHits(SearchHits hits, String... ids) {
}
assertThat(hitIds, containsInAnyOrder(ids));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,18 @@ public void testPhraseQueryOnFieldWithNoPositions() throws Exception {
assertHitCount(resp, 1L);
}

public void testAllFieldsWithSpecifiedLeniency() throws IOException {
String indexBody = copyToStringFromClasspath("/org/elasticsearch/search/query/all-query-index.json");
prepareCreate("test").setSource(indexBody).get();
ensureGreen("test");

Exception e = expectThrows(Exception.class, () ->
client().prepareSearch("test").setQuery(
simpleQueryStringQuery("foo123").lenient(false)).get());
assertThat(ExceptionsHelper.detailedMessage(e),
containsString("NumberFormatException[For input string: \"foo123\"]"));
}

private void assertHits(SearchHits hits, String... ids) {
assertThat(hits.totalHits(), equalTo((long) ids.length));
Set<String> hitIds = new HashSet<>();
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/search/validate.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ due to dynamic mapping, and 'foo' does not correctly parse into a date:

[source,js]
--------------------------------------------------
GET twitter/tweet/_validate/query?q=post_date:foo
GET twitter/tweet/_validate/query?q=post_date:foo%5d
--------------------------------------------------
// CONSOLE

Expand All @@ -102,7 +102,7 @@ about why a query failed:

[source,js]
--------------------------------------------------
GET twitter/tweet/_validate/query?q=post_date:foo&explain=true
GET twitter/tweet/_validate/query?q=post_date:foo%5d&explain=true
--------------------------------------------------
// CONSOLE

Expand Down