Apply slop correctly if phrase query is wrapped in a filtered query.

If a phrase query is wrapped in a filtered query due to type filtering
slop was not applied correctly. Also if the default field required a
type filter the filter was not applied.

Closes #4356
This commit is contained in:
Simon Willnauer 2013-12-06 22:35:24 +01:00
parent 32eb5ffa92
commit dd95895977
3 changed files with 35 additions and 2 deletions

View File

@ -29,6 +29,7 @@ import org.apache.lucene.search.*;
import org.apache.lucene.util.automaton.RegExp;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.lucene.search.XFilteredQuery;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.QueryParseContext;
@ -849,6 +850,9 @@ public class MapperQueryParser extends QueryParser {
}
private void applySlop(Query q, int slop) {
if (q instanceof XFilteredQuery) {
applySlop(((XFilteredQuery)q).getQuery(), slop);
}
if (q instanceof PhraseQuery) {
((PhraseQuery) q).setSlop(slop);
} else if (q instanceof MultiPhraseQuery) {

View File

@ -125,7 +125,7 @@ public class QueryStringQueryParser implements QueryParser {
if ("query".equals(currentFieldName)) {
qpSettings.queryString(parser.text());
} else if ("default_field".equals(currentFieldName) || "defaultField".equals(currentFieldName)) {
qpSettings.defaultField(parseContext.indexName(parser.text()));
qpSettings.defaultField(parser.text());
} else if ("default_operator".equals(currentFieldName) || "defaultOperator".equals(currentFieldName)) {
String op = parser.text();
if ("or".equalsIgnoreCase(op)) {
@ -201,7 +201,6 @@ public class QueryStringQueryParser implements QueryParser {
}
qpSettings.queryTypes(parseContext.queryTypes());
Query query = parseContext.indexCache().queryParserCache().get(qpSettings);
if (query != null) {
return query;

View File

@ -1704,6 +1704,36 @@ public class SimpleQueryTests extends ElasticsearchIntegrationTest {
assertSecondHit(searchResponse, hasId("1"));
}
@Test
public void testQueryStringWithSlopAndFields() {
createIndex("test");
ensureGreen();
client().prepareIndex("test", "customer", "1").setSource("desc", "one two three").get();
client().prepareIndex("test", "product", "2").setSource("desc", "one two three").get();
refresh();
{
SearchResponse searchResponse = client().prepareSearch("test").setQuery(QueryBuilders.queryString("\"one two\"").defaultField("desc")).get();
assertHitCount(searchResponse, 2);
}
{
SearchResponse searchResponse = client().prepareSearch("test").setQuery(QueryBuilders.queryString("\"one two\"").field("product.desc")).get();
assertHitCount(searchResponse, 1);
}
{
SearchResponse searchResponse = client().prepareSearch("test").setQuery(QueryBuilders.queryString("\"one three\"~5").field("product.desc")).get();
assertHitCount(searchResponse, 1);
}
{
SearchResponse searchResponse = client().prepareSearch("test").setQuery(QueryBuilders.queryString("\"one two\"").defaultField("customer.desc")).get();
assertHitCount(searchResponse, 1);
}
{
SearchResponse searchResponse = client().prepareSearch("test").setQuery(QueryBuilders.queryString("\"one two\"").defaultField("customer.desc")).get();
assertHitCount(searchResponse, 1);
}
}
private static FilterBuilder rangeFilter(String field, Object from, Object to) {
if (randomBoolean()) {
if (randomBoolean()) {