blob: 6313e5bb2a2c6d55d01bc93e83931394185be204 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.solr.search;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.complexPhrase.ComplexPhraseQueryParser;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.parser.QueryParser;
import org.apache.solr.request.SolrQueryRequest;
/**
* Parse Solr's variant on the Lucene {@link org.apache.lucene.queryparser.complexPhrase.ComplexPhraseQueryParser} syntax.
* <p>
* Modified from {@link org.apache.solr.search.LuceneQParserPlugin} and {@link org.apache.solr.search.SurroundQParserPlugin}
*/
public class ComplexPhraseQParserPlugin extends QParserPlugin {
public static final String NAME = "complexphrase";
private boolean inOrder = true;
@Override
public void init(@SuppressWarnings({"rawtypes"})NamedList args) {
super.init(args);
if (args != null) {
Object val = args.get("inOrder");
if (val != null) {
inOrder = StrUtils.parseBool(val.toString());
}
}
}
@Override
public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
ComplexPhraseQParser qParser = new ComplexPhraseQParser(qstr, localParams, params, req);
qParser.setInOrder(inOrder);
return qParser;
}
/**
* Modified from {@link org.apache.solr.search.LuceneQParser} and {@link org.apache.solr.search.SurroundQParserPlugin.SurroundQParser}
*/
static class ComplexPhraseQParser extends QParser {
static final class SolrQueryParserDelegate extends SolrQueryParser {
private SolrQueryParserDelegate(QParser parser, String defaultField) {
super(parser, defaultField);
}
@Override
protected org.apache.lucene.search.Query getWildcardQuery(String field, String termStr) throws SyntaxError {
return super.getWildcardQuery(field, termStr);
}
@Override
protected org.apache.lucene.search.Query getRangeQuery(String field, String part1, String part2,
boolean startInclusive, boolean endInclusive) throws SyntaxError {
return super.getRangeQuery(field, part1, part2, startInclusive, endInclusive);
}
@Override
protected boolean isRangeShouldBeProtectedFromReverse(String field, String part1) {
return super.isRangeShouldBeProtectedFromReverse(field, part1);
}
public String getLowerBoundForReverse() {
return REVERSE_WILDCARD_LOWER_BOUND;
}
}
ComplexPhraseQueryParser lparser;
boolean inOrder = true;
/**
* When <code>inOrder</code> is true, the search terms must
* exists in the documents as the same order as in query.
*
* @param inOrder parameter to choose between ordered or un-ordered proximity search
*/
public void setInOrder(final boolean inOrder) {
this.inOrder = inOrder;
}
public ComplexPhraseQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
super(qstr, localParams, params, req);
}
@Override
public Query parse() throws SyntaxError {
String qstr = getString();
String defaultField = getParam(CommonParams.DF);
SolrQueryParserDelegate reverseAwareParser = new SolrQueryParserDelegate(this, defaultField);
lparser = new ComplexPhraseQueryParser(defaultField, getReq().getSchema().getQueryAnalyzer())
{
protected Query newWildcardQuery(org.apache.lucene.index.Term t) {
try {
org.apache.lucene.search.Query wildcardQuery = reverseAwareParser.getWildcardQuery(t.field(), t.text());
setRewriteMethod(wildcardQuery);
return wildcardQuery;
} catch (SyntaxError e) {
throw new RuntimeException(e);
}
}
private Query setRewriteMethod(org.apache.lucene.search.Query query) {
if (query instanceof MultiTermQuery) {
((MultiTermQuery) query).setRewriteMethod(
org.apache.lucene.search.MultiTermQuery.SCORING_BOOLEAN_REWRITE);
}
return query;
}
protected Query newRangeQuery(String field, String part1, String part2, boolean startInclusive,
boolean endInclusive) {
boolean reverse = reverseAwareParser.isRangeShouldBeProtectedFromReverse(field, part1);
return super.newRangeQuery(field,
reverse ? reverseAwareParser.getLowerBoundForReverse() : part1,
part2,
startInclusive || reverse,
endInclusive);
}
}
;
lparser.setAllowLeadingWildcard(true);
if (localParams != null) {
inOrder = localParams.getBool("inOrder", inOrder);
}
lparser.setInOrder(inOrder);
QueryParser.Operator defaultOperator = QueryParsing.parseOP(getParam(QueryParsing.OP));
if (QueryParser.Operator.AND.equals(defaultOperator))
lparser.setDefaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.AND);
else
lparser.setDefaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.OR);
try {
return lparser.parse(qstr);
} catch (ParseException pe) {
throw new SyntaxError(pe);
}
}
@Override
public String[] getDefaultHighlightFields() {
return lparser == null ? new String[]{} : new String[]{lparser.getField()};
}
}
}