Query DSL: query_string syntax to support wildcard fieldnames in the query text, closes #1936.
This commit is contained in:
parent
c6b593595d
commit
cda633afee
|
@ -24,12 +24,11 @@ import org.apache.lucene.analysis.Analyzer;
|
|||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.elasticsearch.common.io.FastStringReader;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
|
||||
|
@ -38,6 +37,7 @@ import org.elasticsearch.index.query.QueryParseContext;
|
|||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded;
|
||||
|
@ -64,6 +64,8 @@ public class MapperQueryParser extends QueryParser {
|
|||
|
||||
private final QueryParseContext parseContext;
|
||||
|
||||
private QueryParserSettings settings;
|
||||
|
||||
private Analyzer quoteAnalyzer;
|
||||
|
||||
private boolean forcedAnalyzer;
|
||||
|
@ -75,8 +77,6 @@ public class MapperQueryParser extends QueryParser {
|
|||
|
||||
private String quoteFieldSuffix;
|
||||
|
||||
private boolean lenient;
|
||||
|
||||
public MapperQueryParser(QueryParseContext parseContext) {
|
||||
super(Lucene.QUERYPARSER_VERSION, null, null);
|
||||
this.parseContext = parseContext;
|
||||
|
@ -89,7 +89,19 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
|
||||
public void reset(QueryParserSettings settings) {
|
||||
this.settings = settings;
|
||||
this.field = settings.defaultField();
|
||||
|
||||
if (settings.fields() != null) {
|
||||
if (settings.fields.size() == 1) {
|
||||
// just mark it as the default field
|
||||
this.field = settings.fields().get(0);
|
||||
} else {
|
||||
// otherwise, we need to have the default field being null...
|
||||
this.field = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.forcedAnalyzer = settings.forcedAnalyzer() != null;
|
||||
this.analyzer = forcedAnalyzer ? settings.forcedAnalyzer() : settings.defaultAnalyzer();
|
||||
if (settings.forcedQuoteAnalyzer() != null) {
|
||||
|
@ -137,6 +149,45 @@ public class MapperQueryParser extends QueryParser {
|
|||
if (fieldQueryExtension != null) {
|
||||
return fieldQueryExtension.query(parseContext, queryText);
|
||||
}
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
if (fields != null) {
|
||||
if (fields.size() == 1) {
|
||||
return getFieldQuerySingle(fields.iterator().next(), queryText, quoted);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String mField : fields) {
|
||||
Query q = getFieldQuerySingle(mField, queryText, quoted);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(mField, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String mField : fields) {
|
||||
Query q = getFieldQuerySingle(mField, queryText, true);
|
||||
if (q != null) {
|
||||
applyBoost(mField, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
} else {
|
||||
return getFieldQuerySingle(field, queryText, quoted);
|
||||
}
|
||||
}
|
||||
|
||||
private Query getFieldQuerySingle(String field, String queryText, boolean quoted) throws ParseException {
|
||||
currentMapper = null;
|
||||
Analyzer oldAnalyzer = analyzer;
|
||||
try {
|
||||
|
@ -176,7 +227,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
query = currentMapper.fieldQuery(queryText, parseContext);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
if (lenient) {
|
||||
if (settings.lenient()) {
|
||||
return null;
|
||||
} else {
|
||||
throw e;
|
||||
|
@ -195,6 +246,45 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getFieldQuery(String field, String queryText, int slop) throws ParseException {
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
if (fields != null) {
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String mField : fields) {
|
||||
Query q = super.getFieldQuery(mField, queryText, slop);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
applySlop(q, slop);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String mField : fields) {
|
||||
Query q = super.getFieldQuery(mField, queryText, slop);
|
||||
if (q != null) {
|
||||
applyBoost(field, q);
|
||||
applySlop(q, slop);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
} else {
|
||||
return super.getFieldQuery(field, queryText, slop);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getRangeQuery(String field, String part1, String part2, boolean inclusive) throws ParseException {
|
||||
if ("*".equals(part1)) {
|
||||
|
@ -203,13 +293,59 @@ public class MapperQueryParser extends QueryParser {
|
|||
if ("*".equals(part2)) {
|
||||
part2 = null;
|
||||
}
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
if (fields != null) {
|
||||
if (fields.size() == 1) {
|
||||
return getRangeQuerySingle(fields.iterator().next(), part1, part2, inclusive);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String mField : fields) {
|
||||
Query q = getRangeQuerySingle(mField, part1, part2, inclusive);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(mField, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String mField : fields) {
|
||||
Query q = getRangeQuerySingle(mField, part1, part2, inclusive);
|
||||
if (q != null) {
|
||||
applyBoost(mField, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
} else {
|
||||
return getRangeQuerySingle(field, part1, part2, inclusive);
|
||||
}
|
||||
}
|
||||
|
||||
private Query getRangeQuerySingle(String field, String part1, String part2, boolean inclusive) {
|
||||
currentMapper = null;
|
||||
MapperService.SmartNameFieldMappers fieldMappers = parseContext.smartFieldMappers(field);
|
||||
if (fieldMappers != null) {
|
||||
currentMapper = fieldMappers.fieldMappers().mapper();
|
||||
if (currentMapper != null) {
|
||||
Query rangeQuery = currentMapper.rangeQuery(part1, part2, inclusive, inclusive, parseContext);
|
||||
return wrapSmartNameQuery(rangeQuery, fieldMappers, parseContext);
|
||||
try {
|
||||
Query rangeQuery = currentMapper.rangeQuery(part1, part2, inclusive, inclusive, parseContext);
|
||||
return wrapSmartNameQuery(rangeQuery, fieldMappers, parseContext);
|
||||
} catch (RuntimeException e) {
|
||||
if (settings.lenient()) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newRangeQuery(field, part1, part2, inclusive);
|
||||
|
@ -217,13 +353,55 @@ public class MapperQueryParser extends QueryParser {
|
|||
|
||||
@Override
|
||||
protected Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException {
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
if (fields != null) {
|
||||
if (fields.size() == 1) {
|
||||
return getFuzzyQuerySingle(fields.iterator().next(), termStr, minSimilarity);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String mField : fields) {
|
||||
Query q = getFuzzyQuerySingle(mField, termStr, minSimilarity);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(mField, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String mField : fields) {
|
||||
Query q = getFuzzyQuerySingle(mField, termStr, minSimilarity);
|
||||
applyBoost(mField, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
} else {
|
||||
return getFuzzyQuerySingle(field, termStr, minSimilarity);
|
||||
}
|
||||
}
|
||||
|
||||
private Query getFuzzyQuerySingle(String field, String termStr, float minSimilarity) throws ParseException {
|
||||
currentMapper = null;
|
||||
MapperService.SmartNameFieldMappers fieldMappers = parseContext.smartFieldMappers(field);
|
||||
if (fieldMappers != null) {
|
||||
currentMapper = fieldMappers.fieldMappers().mapper();
|
||||
if (currentMapper != null) {
|
||||
Query fuzzyQuery = currentMapper.fuzzyQuery(termStr, minSimilarity, fuzzyPrefixLength, FuzzyQuery.defaultMaxExpansions);
|
||||
return wrapSmartNameQuery(fuzzyQuery, fieldMappers, parseContext);
|
||||
try {
|
||||
Query fuzzyQuery = currentMapper.fuzzyQuery(termStr, minSimilarity, fuzzyPrefixLength, FuzzyQuery.defaultMaxExpansions);
|
||||
return wrapSmartNameQuery(fuzzyQuery, fieldMappers, parseContext);
|
||||
} catch (RuntimeException e) {
|
||||
if (settings.lenient()) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getFuzzyQuery(field, termStr, minSimilarity);
|
||||
|
@ -231,6 +409,45 @@ public class MapperQueryParser extends QueryParser {
|
|||
|
||||
@Override
|
||||
protected Query getPrefixQuery(String field, String termStr) throws ParseException {
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
if (fields != null) {
|
||||
if (fields.size() == 1) {
|
||||
return getPrefixQuerySingle(fields.iterator().next(), termStr);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String mField : fields) {
|
||||
Query q = getPrefixQuerySingle(mField, termStr);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(mField, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String mField : fields) {
|
||||
Query q = getPrefixQuerySingle(mField, termStr);
|
||||
if (q != null) {
|
||||
applyBoost(mField, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
} else {
|
||||
return getPrefixQuerySingle(field, termStr);
|
||||
}
|
||||
}
|
||||
|
||||
private Query getPrefixQuerySingle(String field, String termStr) throws ParseException {
|
||||
currentMapper = null;
|
||||
Analyzer oldAnalyzer = analyzer;
|
||||
try {
|
||||
|
@ -261,6 +478,11 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
}
|
||||
return getPossiblyAnalyzedPrefixQuery(field, termStr);
|
||||
} catch (RuntimeException e) {
|
||||
if (settings.lenient()) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
analyzer = oldAnalyzer;
|
||||
}
|
||||
|
@ -321,6 +543,45 @@ public class MapperQueryParser extends QueryParser {
|
|||
if (AllFieldMapper.NAME.equals(field) && termStr.equals("*")) {
|
||||
return newMatchAllDocsQuery();
|
||||
}
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
if (fields != null) {
|
||||
if (fields.size() == 1) {
|
||||
return getWildcardQuerySingle(fields.iterator().next(), termStr);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String mField : fields) {
|
||||
Query q = getWildcardQuerySingle(mField, termStr);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(mField, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String mField : fields) {
|
||||
Query q = getWildcardQuerySingle(mField, termStr);
|
||||
if (q != null) {
|
||||
applyBoost(mField, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
} else {
|
||||
return getWildcardQuerySingle(field, termStr);
|
||||
}
|
||||
}
|
||||
|
||||
private Query getWildcardQuerySingle(String field, String termStr) throws ParseException {
|
||||
String indexedNameField = field;
|
||||
currentMapper = null;
|
||||
Analyzer oldAnalyzer = analyzer;
|
||||
|
@ -337,6 +598,11 @@ public class MapperQueryParser extends QueryParser {
|
|||
return wrapSmartNameQuery(getPossiblyAnalyzedWildcardQuery(indexedNameField, termStr), fieldMappers, parseContext);
|
||||
}
|
||||
return getPossiblyAnalyzedWildcardQuery(indexedNameField, termStr);
|
||||
} catch (RuntimeException e) {
|
||||
if (settings.lenient()) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
analyzer = oldAnalyzer;
|
||||
}
|
||||
|
@ -414,4 +680,31 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
return optimizeQuery(fixNegativeQueryIfNeeded(q));
|
||||
}
|
||||
|
||||
private void applyBoost(String field, Query q) {
|
||||
if (settings.boosts() != null) {
|
||||
float boost = settings.boosts().get(field);
|
||||
q.setBoost(boost);
|
||||
}
|
||||
}
|
||||
|
||||
private void applySlop(Query q, int slop) {
|
||||
if (q instanceof PhraseQuery) {
|
||||
((PhraseQuery) q).setSlop(slop);
|
||||
} else if (q instanceof MultiPhraseQuery) {
|
||||
((MultiPhraseQuery) q).setSlop(slop);
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<String> extractMultiFields(String field) {
|
||||
Collection<String> fields = null;
|
||||
if (field != null) {
|
||||
if (Regex.isSimpleMatchPattern(field)) {
|
||||
fields = parseContext.mapperService().simpleMatchToIndexNames(field);
|
||||
}
|
||||
} else {
|
||||
fields = settings.fields();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,273 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch licenses this
|
||||
* file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.queryParser;
|
||||
|
||||
import org.apache.lucene.search.*;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MultiFieldMapperQueryParser extends MapperQueryParser {
|
||||
|
||||
private MultiFieldQueryParserSettings settings;
|
||||
|
||||
public MultiFieldMapperQueryParser(QueryParseContext parseContext) {
|
||||
super(parseContext);
|
||||
}
|
||||
|
||||
public MultiFieldMapperQueryParser(MultiFieldQueryParserSettings settings, QueryParseContext parseContext) {
|
||||
super(settings, parseContext);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public void reset(MultiFieldQueryParserSettings settings) {
|
||||
super.reset(settings);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getFieldQuery(String xField, String queryText, boolean quoted) throws ParseException {
|
||||
if (xField != null) {
|
||||
return super.getFieldQuery(xField, queryText, quoted);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getFieldQuery(field, queryText, quoted);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getFieldQuery(field, queryText, true);
|
||||
if (q != null) {
|
||||
applyBoost(field, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query getFieldQuery(String xField, String queryText, int slop) throws ParseException {
|
||||
if (xField != null) {
|
||||
Query q = super.getFieldQuery(xField, queryText, true);
|
||||
applySlop(q, slop);
|
||||
return q;
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getFieldQuery(field, queryText, true);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
applySlop(q, slop);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getFieldQuery(field, queryText, true);
|
||||
if (q != null) {
|
||||
applyBoost(field, q);
|
||||
applySlop(q, slop);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getRangeQuery(String xField, String part1, String part2, boolean inclusive) throws ParseException {
|
||||
if (xField != null) {
|
||||
return super.getRangeQuery(xField, part1, part2, inclusive);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getRangeQuery(field, part1, part2, inclusive);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getRangeQuery(field, part1, part2, inclusive);
|
||||
if (q != null) {
|
||||
applyBoost(field, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getPrefixQuery(String xField, String termStr) throws ParseException {
|
||||
if (xField != null) {
|
||||
return super.getPrefixQuery(xField, termStr);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getPrefixQuery(field, termStr);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getPrefixQuery(field, termStr);
|
||||
if (q != null) {
|
||||
applyBoost(field, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getWildcardQuery(String xField, String termStr) throws ParseException {
|
||||
if (xField != null) {
|
||||
return super.getWildcardQuery(xField, termStr);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getWildcardQuery(field, termStr);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getWildcardQuery(field, termStr);
|
||||
if (q != null) {
|
||||
applyBoost(field, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
if (clauses.size() == 0) // happens for stopwords
|
||||
return null;
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getFuzzyQuery(String xField, String termStr, float minSimilarity) throws ParseException {
|
||||
if (xField != null) {
|
||||
return super.getFuzzyQuery(xField, termStr, minSimilarity);
|
||||
}
|
||||
if (settings.useDisMax()) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(settings.tieBreaker());
|
||||
boolean added = false;
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getFuzzyQuery(field, termStr, minSimilarity);
|
||||
if (q != null) {
|
||||
added = true;
|
||||
applyBoost(field, q);
|
||||
disMaxQuery.add(q);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
return null;
|
||||
}
|
||||
return disMaxQuery;
|
||||
} else {
|
||||
List<BooleanClause> clauses = new ArrayList<BooleanClause>();
|
||||
for (String field : settings.fields()) {
|
||||
Query q = super.getFuzzyQuery(field, termStr, minSimilarity);
|
||||
applyBoost(field, q);
|
||||
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
return getBooleanQuery(clauses, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyBoost(String field, Query q) {
|
||||
if (settings.boosts() != null) {
|
||||
float boost = settings.boosts().get(field);
|
||||
q.setBoost(boost);
|
||||
}
|
||||
}
|
||||
|
||||
private void applySlop(Query q, int slop) {
|
||||
if (q instanceof PhraseQuery) {
|
||||
((PhraseQuery) q).setSlop(slop);
|
||||
} else if (q instanceof MultiPhraseQuery) {
|
||||
((MultiPhraseQuery) q).setSlop(slop);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch licenses this
|
||||
* file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.queryParser;
|
||||
|
||||
import gnu.trove.map.hash.TObjectFloatHashMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MultiFieldQueryParserSettings extends QueryParserSettings {
|
||||
|
||||
List<String> fields = null;
|
||||
TObjectFloatHashMap<String> boosts = null;
|
||||
float tieBreaker = 0.0f;
|
||||
boolean useDisMax = true;
|
||||
|
||||
public List<String> fields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void fields(List<String> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public TObjectFloatHashMap<String> boosts() {
|
||||
return boosts;
|
||||
}
|
||||
|
||||
public void boosts(TObjectFloatHashMap<String> boosts) {
|
||||
this.boosts = boosts;
|
||||
}
|
||||
|
||||
public float tieBreaker() {
|
||||
return tieBreaker;
|
||||
}
|
||||
|
||||
public void tieBreaker(float tieBreaker) {
|
||||
this.tieBreaker = tieBreaker;
|
||||
}
|
||||
|
||||
public boolean useDisMax() {
|
||||
return useDisMax;
|
||||
}
|
||||
|
||||
public void useDisMax(boolean useDisMax) {
|
||||
this.useDisMax = useDisMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
// if there is a single field, its the same as single mapper parser / settings
|
||||
// we take for that also in the code
|
||||
if (fields == null || fields.size() == 1) return super.equals(o);
|
||||
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
MultiFieldQueryParserSettings that = (MultiFieldQueryParserSettings) o;
|
||||
|
||||
if (Float.compare(that.tieBreaker, tieBreaker) != 0) return false;
|
||||
if (useDisMax != that.useDisMax) return false;
|
||||
if (boosts != null ? !boosts.equals(that.boosts) : that.boosts != null) return false;
|
||||
if (fields != null ? !fields.equals(that.fields) : that.fields != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (fields != null ? fields.hashCode() : 0);
|
||||
result = 31 * result + (boosts != null ? boosts.hashCode() : 0);
|
||||
result = 31 * result + (tieBreaker != +0.0f ? Float.floatToIntBits(tieBreaker) : 0);
|
||||
result = 31 * result + (useDisMax ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -19,10 +19,13 @@
|
|||
|
||||
package org.apache.lucene.queryParser;
|
||||
|
||||
import gnu.trove.map.hash.TObjectFloatHashMap;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.MultiTermQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -53,6 +56,12 @@ public class QueryParserSettings {
|
|||
private String minimumShouldMatch;
|
||||
private boolean lenient;
|
||||
|
||||
|
||||
List<String> fields = null;
|
||||
TObjectFloatHashMap<String> boosts = null;
|
||||
float tieBreaker = 0.0f;
|
||||
boolean useDisMax = true;
|
||||
|
||||
public String queryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
@ -221,6 +230,38 @@ public class QueryParserSettings {
|
|||
return this.lenient;
|
||||
}
|
||||
|
||||
public List<String> fields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void fields(List<String> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public TObjectFloatHashMap<String> boosts() {
|
||||
return boosts;
|
||||
}
|
||||
|
||||
public void boosts(TObjectFloatHashMap<String> boosts) {
|
||||
this.boosts = boosts;
|
||||
}
|
||||
|
||||
public float tieBreaker() {
|
||||
return tieBreaker;
|
||||
}
|
||||
|
||||
public void tieBreaker(float tieBreaker) {
|
||||
this.tieBreaker = tieBreaker;
|
||||
}
|
||||
|
||||
public boolean useDisMax() {
|
||||
return useDisMax;
|
||||
}
|
||||
|
||||
public void useDisMax(boolean useDisMax) {
|
||||
this.useDisMax = useDisMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -259,6 +300,11 @@ public class QueryParserSettings {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Float.compare(that.tieBreaker, tieBreaker) != 0) return false;
|
||||
if (useDisMax != that.useDisMax) return false;
|
||||
if (boosts != null ? !boosts.equals(that.boosts) : that.boosts != null) return false;
|
||||
if (fields != null ? !fields.equals(that.fields) : that.fields != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -281,6 +327,11 @@ public class QueryParserSettings {
|
|||
result = 31 * result + (forcedAnalyzer != null ? forcedAnalyzer.hashCode() : 0);
|
||||
result = 31 * result + (forcedQuoteAnalyzer != null ? forcedQuoteAnalyzer.hashCode() : 0);
|
||||
result = 31 * result + (analyzeWildcard ? 1 : 0);
|
||||
|
||||
result = 31 * result + (fields != null ? fields.hashCode() : 0);
|
||||
result = 31 * result + (boosts != null ? boosts.hashCode() : 0);
|
||||
result = 31 * result + (tieBreaker != +0.0f ? Float.floatToIntBits(tieBreaker) : 0);
|
||||
result = 31 * result + (useDisMax ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ public class FieldQueryParser implements QueryParser {
|
|||
return query;
|
||||
}
|
||||
|
||||
MapperQueryParser queryParser = parseContext.singleQueryParser(qpSettings);
|
||||
MapperQueryParser queryParser = parseContext.queryParser(qpSettings);
|
||||
|
||||
try {
|
||||
query = queryParser.parse(qpSettings.queryString());
|
||||
|
|
|
@ -22,8 +22,6 @@ package org.elasticsearch.index.query;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.lucene.queryParser.MapperQueryParser;
|
||||
import org.apache.lucene.queryParser.MultiFieldMapperQueryParser;
|
||||
import org.apache.lucene.queryParser.MultiFieldQueryParserSettings;
|
||||
import org.apache.lucene.queryParser.QueryParserSettings;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.Query;
|
||||
|
@ -81,8 +79,6 @@ public class QueryParseContext {
|
|||
|
||||
private final MapperQueryParser queryParser = new MapperQueryParser(this);
|
||||
|
||||
private final MultiFieldMapperQueryParser multiFieldQueryParser = new MultiFieldMapperQueryParser(this);
|
||||
|
||||
private XContentParser parser;
|
||||
|
||||
public QueryParseContext(Index index, IndexQueryParserService indexQueryParser) {
|
||||
|
@ -141,16 +137,11 @@ public class QueryParseContext {
|
|||
return indexQueryParser.queryStringLenient();
|
||||
}
|
||||
|
||||
public MapperQueryParser singleQueryParser(QueryParserSettings settings) {
|
||||
public MapperQueryParser queryParser(QueryParserSettings settings) {
|
||||
queryParser.reset(settings);
|
||||
return queryParser;
|
||||
}
|
||||
|
||||
public MultiFieldMapperQueryParser multiQueryParser(MultiFieldQueryParserSettings settings) {
|
||||
multiFieldQueryParser.reset(settings);
|
||||
return multiFieldQueryParser;
|
||||
}
|
||||
|
||||
public Filter cacheFilter(Filter filter, @Nullable CacheKeyFilter.Key cacheKey) {
|
||||
if (cacheKey != null) {
|
||||
filter = new CacheKeyFilter.Wrapper(filter, cacheKey);
|
||||
|
|
|
@ -23,7 +23,6 @@ import com.google.common.collect.Lists;
|
|||
import gnu.trove.impl.Constants;
|
||||
import gnu.trove.map.hash.TObjectFloatHashMap;
|
||||
import org.apache.lucene.queryParser.MapperQueryParser;
|
||||
import org.apache.lucene.queryParser.MultiFieldQueryParserSettings;
|
||||
import org.apache.lucene.queryParser.ParseException;
|
||||
import org.apache.lucene.queryParser.QueryParserSettings;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
@ -67,7 +66,7 @@ public class QueryStringQueryParser implements QueryParser {
|
|||
public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
|
||||
MultiFieldQueryParserSettings qpSettings = new MultiFieldQueryParserSettings();
|
||||
QueryParserSettings qpSettings = new QueryParserSettings();
|
||||
qpSettings.defaultField(parseContext.defaultField());
|
||||
qpSettings.lenient(parseContext.queryStringLenient());
|
||||
qpSettings.analyzeWildcard(defaultAnalyzeWildcard);
|
||||
|
@ -201,19 +200,7 @@ public class QueryStringQueryParser implements QueryParser {
|
|||
return query;
|
||||
}
|
||||
|
||||
MapperQueryParser queryParser;
|
||||
if (qpSettings.fields() != null) {
|
||||
if (qpSettings.fields().size() == 1) {
|
||||
qpSettings.defaultField(qpSettings.fields().get(0));
|
||||
queryParser = parseContext.singleQueryParser(qpSettings);
|
||||
} else {
|
||||
qpSettings.defaultField(null); // reset defaultField when using multi query parser
|
||||
queryParser = parseContext.multiQueryParser(qpSettings);
|
||||
}
|
||||
} else {
|
||||
queryParser = parseContext.singleQueryParser(qpSettings);
|
||||
}
|
||||
|
||||
MapperQueryParser queryParser = parseContext.queryParser(qpSettings);
|
||||
|
||||
try {
|
||||
query = queryParser.parse(qpSettings.queryString());
|
||||
|
|
Loading…
Reference in New Issue