refactor SimpleQueryParser settings into separate class, add "lenient" option
Fixes #5011
This commit is contained in:
parent
90e57c15e8
commit
5429019920
|
@ -38,14 +38,31 @@ import static org.elasticsearch.index.query.support.QueryParsers.wrapSmartNameQu
|
|||
*/
|
||||
public class SimpleQueryParser extends XSimpleQueryParser {
|
||||
|
||||
private final boolean lowercaseExpandedTerms;
|
||||
private final Locale locale;
|
||||
private final Settings settings;
|
||||
|
||||
/** Creates a new parser with custom flags used to enable/disable certain features. */
|
||||
public SimpleQueryParser(Analyzer analyzer, Map<String, Float> weights, int flags, Locale locale, boolean lowercaseExpandedTerms) {
|
||||
public SimpleQueryParser(Analyzer analyzer, Map<String, Float> weights, int flags, Settings settings) {
|
||||
super(analyzer, weights, flags);
|
||||
this.lowercaseExpandedTerms = lowercaseExpandedTerms;
|
||||
this.locale = locale;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rethrow the runtime exception, unless the lenient flag has been set, returns null
|
||||
*/
|
||||
private Query rethrowUnlessLenient(RuntimeException e) {
|
||||
if (settings.lenient()) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query newDefaultQuery(String text) {
|
||||
try {
|
||||
return super.newDefaultQuery(text);
|
||||
} catch (RuntimeException e) {
|
||||
return rethrowUnlessLenient(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,10 +71,23 @@ public class SimpleQueryParser extends XSimpleQueryParser {
|
|||
*/
|
||||
@Override
|
||||
public Query newFuzzyQuery(String text, int fuzziness) {
|
||||
if (lowercaseExpandedTerms) {
|
||||
text = text.toLowerCase(locale);
|
||||
if (settings.lowercaseExpandedTerms()) {
|
||||
text = text.toLowerCase(settings.locale());
|
||||
}
|
||||
try {
|
||||
return super.newFuzzyQuery(text, fuzziness);
|
||||
} catch (RuntimeException e) {
|
||||
return rethrowUnlessLenient(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query newPhraseQuery(String text, int slop) {
|
||||
try {
|
||||
return super.newPhraseQuery(text, slop);
|
||||
} catch (RuntimeException e) {
|
||||
return rethrowUnlessLenient(e);
|
||||
}
|
||||
return super.newFuzzyQuery(text, fuzziness);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,9 +96,51 @@ public class SimpleQueryParser extends XSimpleQueryParser {
|
|||
*/
|
||||
@Override
|
||||
public Query newPrefixQuery(String text) {
|
||||
if (lowercaseExpandedTerms) {
|
||||
text = text.toLowerCase(locale);
|
||||
if (settings.lowercaseExpandedTerms()) {
|
||||
text = text.toLowerCase(settings.locale());
|
||||
}
|
||||
try {
|
||||
return super.newPrefixQuery(text);
|
||||
} catch (RuntimeException e) {
|
||||
return rethrowUnlessLenient(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class encapsulating the settings for the SimpleQueryString query, with
|
||||
* their default values
|
||||
*/
|
||||
public static class Settings {
|
||||
private Locale locale = Locale.ROOT;
|
||||
private boolean lowercaseExpandedTerms = true;
|
||||
private boolean lenient = false;
|
||||
|
||||
public Settings() {
|
||||
|
||||
}
|
||||
|
||||
public void locale(Locale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public Locale locale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
public void lowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
|
||||
this.lowercaseExpandedTerms = lowercaseExpandedTerms;
|
||||
}
|
||||
|
||||
public boolean lowercaseExpandedTerms() {
|
||||
return this.lowercaseExpandedTerms;
|
||||
}
|
||||
|
||||
public void lenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
}
|
||||
|
||||
public boolean lenient() {
|
||||
return this.lenient;
|
||||
}
|
||||
return super.newPrefixQuery(text);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
|
|||
private final String queryText;
|
||||
private int flags = -1;
|
||||
private Boolean lowercaseExpandedTerms;
|
||||
private Boolean lenient;
|
||||
private Locale locale;
|
||||
|
||||
/**
|
||||
|
@ -113,6 +114,11 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public SimpleQueryStringBuilder lenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(SimpleQueryStringParser.NAME);
|
||||
|
@ -149,6 +155,10 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
|
|||
builder.field("lowercase_expanded_terms", lowercaseExpandedTerms);
|
||||
}
|
||||
|
||||
if (lenient != null) {
|
||||
builder.field("lenient", lenient);
|
||||
}
|
||||
|
||||
if (locale != null) {
|
||||
builder.field("locale", locale.toString());
|
||||
}
|
||||
|
|
|
@ -92,9 +92,8 @@ public class SimpleQueryStringParser implements QueryParser {
|
|||
Map<String, Float> fieldsAndWeights = null;
|
||||
BooleanClause.Occur defaultOperator = null;
|
||||
Analyzer analyzer = null;
|
||||
boolean lowercaseExpandedTerms = true;
|
||||
Locale locale = Locale.ROOT;
|
||||
int flags = -1;
|
||||
SimpleQueryParser.Settings sqsSettings = new SimpleQueryParser.Settings();
|
||||
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
|
@ -173,9 +172,12 @@ public class SimpleQueryStringParser implements QueryParser {
|
|||
}
|
||||
} else if ("locale".equals(currentFieldName)) {
|
||||
String localeStr = parser.text();
|
||||
locale = LocaleUtils.parse(localeStr);
|
||||
Locale locale = LocaleUtils.parse(localeStr);
|
||||
sqsSettings.locale(locale);
|
||||
} else if ("lowercase_expanded_terms".equals(currentFieldName)) {
|
||||
lowercaseExpandedTerms = parser.booleanValue();
|
||||
sqsSettings.lowercaseExpandedTerms(parser.booleanValue());
|
||||
} else if ("lenient".equals(currentFieldName)) {
|
||||
sqsSettings.lenient(parser.booleanValue());
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[" + NAME + "] unsupported field [" + parser.currentName() + "]");
|
||||
}
|
||||
|
@ -205,7 +207,7 @@ public class SimpleQueryStringParser implements QueryParser {
|
|||
if (fieldsAndWeights == null) {
|
||||
fieldsAndWeights = Collections.singletonMap(field, 1.0F);
|
||||
}
|
||||
SimpleQueryParser sqp = new SimpleQueryParser(analyzer, fieldsAndWeights, flags, locale, lowercaseExpandedTerms);
|
||||
SimpleQueryParser sqp = new SimpleQueryParser(analyzer, fieldsAndWeights, flags, sqsSettings);
|
||||
|
||||
if (defaultOperator != null) {
|
||||
sqp.setDefaultOperator(defaultOperator);
|
||||
|
|
|
@ -2120,6 +2120,25 @@ public class SimpleQueryTests extends ElasticsearchIntegrationTest {
|
|||
assertFirstHit(searchResponse, hasId("4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleQueryStringLenient() {
|
||||
assertAcked(client().admin().indices().prepareCreate("test1").setSettings(SETTING_NUMBER_OF_SHARDS, 1));
|
||||
assertAcked(client().admin().indices().prepareCreate("test2").setSettings(SETTING_NUMBER_OF_SHARDS, 1));
|
||||
client().prepareIndex("test1", "type1", "1").setSource("field", "foo").get();
|
||||
client().prepareIndex("test2", "type1", "10").setSource("field", 5).get();
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch().setQuery(simpleQueryString("foo").field("field")).get();
|
||||
assertFailures(searchResponse);
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertSearchHits(searchResponse, "1");
|
||||
|
||||
searchResponse = client().prepareSearch().setQuery(simpleQueryString("foo").field("field").lenient(true)).get();
|
||||
assertNoFailures(searchResponse);
|
||||
assertHitCount(searchResponse, 1l);
|
||||
assertSearchHits(searchResponse, "1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRangeFilterNoCacheWithNow() throws Exception {
|
||||
assertAcked(client().admin().indices().prepareCreate("test")
|
||||
|
|
Loading…
Reference in New Issue