fix #2707 add QueryParser

This commit is contained in:
Shinsuke Sugaya 2023-01-05 06:02:17 +09:00
parent 352a6c25a7
commit 679e106739
7 changed files with 151 additions and 24 deletions

View file

@ -0,0 +1,28 @@
/*
* Copyright 2012-2023 CodeLibs Project and the Others.
*
* Licensed 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.codelibs.fess.exception;
import org.apache.lucene.queryparser.classic.ParseException;
public class QueryParseException extends FessSystemException {
private static final long serialVersionUID = 1L;
public QueryParseException(final ParseException cause) {
super(cause);
}
}

View file

@ -30,8 +30,6 @@ import javax.servlet.http.HttpSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.Query;
import org.codelibs.core.lang.StringUtil;
import org.codelibs.fess.Constants;
@ -40,9 +38,11 @@ import org.codelibs.fess.entity.GeoInfo;
import org.codelibs.fess.entity.QueryContext;
import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
import org.codelibs.fess.exception.InvalidQueryException;
import org.codelibs.fess.exception.QueryParseException;
import org.codelibs.fess.mylasta.action.FessUserBean;
import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.query.QueryFieldConfig;
import org.codelibs.fess.query.parser.QueryParser;
import org.codelibs.fess.score.QueryRescorer;
import org.codelibs.fess.util.ComponentUtil;
import org.dbflute.optional.OptionalThing;
@ -158,7 +158,7 @@ public class QueryHelper {
}
// TODO options query
context.accept(queryContext);
} catch (final ParseException e) {
} catch (final QueryParseException e) {
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryParseError(UserMessages.GLOBAL_PROPERTY_KEY),
"Invalid query: " + queryContext.getQueryString(), e);
}

View file

@ -0,0 +1,112 @@
/*
* Copyright 2012-2023 CodeLibs Project and the Others.
*
* Licensed 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.codelibs.fess.query.parser;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser.Operator;
import org.apache.lucene.queryparser.ext.ExtendableQueryParser;
import org.apache.lucene.search.Query;
import org.codelibs.fess.Constants;
import org.codelibs.fess.exception.QueryParseException;
public class QueryParser {
protected String defaultField = Constants.DEFAULT_FIELD;
protected Analyzer analyzer = new WhitespaceAnalyzer();
protected boolean allowLeadingWildcard = true;
protected Operator defaultOperator = Operator.AND;
protected List<Filter> filterList = new ArrayList<>();
protected FilterChain filterChain;
@PostConstruct
public void init() {
createFilterChain();
}
public Query parse(final String query) {
return filterChain.parse(query);
}
protected org.apache.lucene.queryparser.classic.QueryParser createQueryParser() {
final ExtendableQueryParser parser = new ExtendableQueryParser(defaultField, analyzer);
parser.setAllowLeadingWildcard(allowLeadingWildcard);
parser.setDefaultOperator(defaultOperator);
return parser;
}
public void setDefaultField(final String defaultField) {
this.defaultField = defaultField;
}
public void setAnalyzer(final Analyzer analyzer) {
this.analyzer = analyzer;
}
public void setAllowLeadingWildcard(final boolean allowLeadingWildcard) {
this.allowLeadingWildcard = allowLeadingWildcard;
}
public void setDefaultOperator(final Operator defaultOperator) {
this.defaultOperator = defaultOperator;
}
public void addFilter(final Filter filter) {
filterList.add(filter);
createFilterChain();
}
protected void createFilterChain() {
FilterChain chain = createDefaultFilterChain();
for (final Filter element : filterList) {
chain = appendFilterChain(element, chain);
}
filterChain = chain;
}
protected FilterChain appendFilterChain(final Filter filter, final FilterChain chain) {
return query -> filter.parse(query, chain);
}
protected FilterChain createDefaultFilterChain() {
return query -> {
try {
return createQueryParser().parse(query);
} catch (final ParseException e) {
throw new QueryParseException(e);
}
};
}
public interface Filter {
Query parse(final String query, final FilterChain chain);
}
public interface FilterChain {
Query parse(final String query);
}
}

View file

@ -23,7 +23,6 @@ import java.util.function.Consumer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.codelibs.core.crypto.CachedCipher;
import org.codelibs.core.misc.DynamicProperties;
import org.codelibs.fess.api.WebApiManagerFactory;
@ -80,6 +79,7 @@ import org.codelibs.fess.mylasta.direction.FessConfig;
import org.codelibs.fess.mylasta.direction.FessProp;
import org.codelibs.fess.query.QueryFieldConfig;
import org.codelibs.fess.query.QueryProcessor;
import org.codelibs.fess.query.parser.QueryParser;
import org.codelibs.fess.script.ScriptEngineFactory;
import org.codelibs.fess.sso.SsoManager;
import org.codelibs.fess.thumbnail.ThumbnailManager;

View file

@ -41,13 +41,7 @@
</component>
<component name="queryStringBuilder" class="org.codelibs.fess.util.QueryStringBuilder" instance="prototype">
</component>
<component name="queryParser" class="org.apache.lucene.queryparser.ext.ExtendableQueryParser" instance="prototype">
<arg>org.codelibs.fess.Constants.DEFAULT_FIELD</arg>
<arg>
<component class="org.apache.lucene.analysis.core.WhitespaceAnalyzer"></component>
</arg>
<property name="allowLeadingWildcard">true</property>
<property name="defaultOperator">org.apache.lucene.queryparser.classic.QueryParser$Operator.AND</property>
<component name="queryParser" class="org.codelibs.fess.query.parser.QueryParser">
</component>
<component name="facetInfo" class="org.codelibs.fess.entity.FacetInfo">
</component>

View file

@ -21,9 +21,6 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.queryparser.ext.ExtendableQueryParser;
import org.codelibs.core.io.FileUtil;
import org.codelibs.core.misc.DynamicProperties;
import org.codelibs.fess.Constants;
@ -41,6 +38,7 @@ import org.codelibs.fess.query.QueryProcessor;
import org.codelibs.fess.query.TermQueryCommand;
import org.codelibs.fess.query.TermRangeQueryCommand;
import org.codelibs.fess.query.WildcardQueryCommand;
import org.codelibs.fess.query.parser.QueryParser;
import org.codelibs.fess.unit.UnitFessTestCase;
import org.codelibs.fess.util.ComponentUtil;
import org.opensearch.index.query.BoolQueryBuilder;
@ -59,9 +57,8 @@ public class QueryHelperTest extends UnitFessTestCase {
super.setUp();
queryHelper = new QueryHelper() {
protected QueryParser getQueryParser() {
ExtendableQueryParser queryParser = new ExtendableQueryParser(Constants.DEFAULT_FIELD, new WhitespaceAnalyzer());
queryParser.setAllowLeadingWildcard(true);
queryParser.setDefaultOperator(QueryParser.Operator.AND);
QueryParser queryParser = new QueryParser();
queryParser.init();
return queryParser;
}
};

View file

@ -19,14 +19,11 @@ import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.queryparser.classic.QueryParser.Operator;
import org.apache.lucene.queryparser.ext.ExtendableQueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.codelibs.fess.Constants;
import org.codelibs.fess.entity.QueryContext;
import org.codelibs.fess.exception.InvalidQueryException;
import org.codelibs.fess.query.parser.QueryParser;
import org.codelibs.fess.unit.UnitFessTestCase;
import org.codelibs.fess.util.ComponentUtil;
import org.opensearch.index.query.BoolQueryBuilder;
@ -50,9 +47,8 @@ public class TermQueryCommandTest extends UnitFessTestCase {
queryFieldConfig.init();
ComponentUtil.register(queryFieldConfig, "queryFieldConfig");
ExtendableQueryParser queryParser = new ExtendableQueryParser(Constants.DEFAULT_FIELD, new WhitespaceAnalyzer());
queryParser.setAllowLeadingWildcard(true);
queryParser.setDefaultOperator(Operator.AND);
QueryParser queryParser = new QueryParser();
queryParser.init();
ComponentUtil.register(queryParser, "queryParser");
queryCommand = new TermQueryCommand();