fix #2638 add query filter
This commit is contained in:
parent
bf6751dc7c
commit
f92fd3fa9d
10 changed files with 170 additions and 22 deletions
|
@ -57,7 +57,7 @@ public class FuzzyQueryCommand extends QueryCommand {
|
|||
// TODO fuzzy value
|
||||
if (Constants.DEFAULT_FIELD.equals(field)) {
|
||||
context.addFieldLog(field, term.text());
|
||||
return buildDefaultQueryBuilder(
|
||||
return buildDefaultQueryBuilder(fessConfig, context,
|
||||
(f, b) -> QueryBuilders.fuzzyQuery(f, term.text()).fuzziness(Fuzziness.fromEdits(fuzzyQuery.getMaxEdits()))
|
||||
.boost(b * boost).maxExpansions(fessConfig.getQueryFuzzyExpansionsAsInteger())
|
||||
.prefixLength(fessConfig.getQueryFuzzyPrefixLengthAsInteger())
|
||||
|
@ -73,9 +73,10 @@ public class FuzzyQueryCommand extends QueryCommand {
|
|||
final String origQuery = fuzzyQuery.toString();
|
||||
context.addFieldLog(Constants.DEFAULT_FIELD, origQuery);
|
||||
context.addHighlightedQuery(origQuery);
|
||||
return buildDefaultQueryBuilder((f, b) -> QueryBuilders.fuzzyQuery(f, origQuery)
|
||||
.fuzziness(Fuzziness.fromEdits(fuzzyQuery.getMaxEdits())).boost(b * boost)
|
||||
.maxExpansions(fessConfig.getQueryFuzzyExpansionsAsInteger()).prefixLength(fessConfig.getQueryFuzzyPrefixLengthAsInteger())
|
||||
.transpositions(Constants.TRUE.equalsIgnoreCase(fessConfig.getQueryFuzzyTranspositions())));
|
||||
return buildDefaultQueryBuilder(fessConfig, context,
|
||||
(f, b) -> QueryBuilders.fuzzyQuery(f, origQuery).fuzziness(Fuzziness.fromEdits(fuzzyQuery.getMaxEdits())).boost(b * boost)
|
||||
.maxExpansions(fessConfig.getQueryFuzzyExpansionsAsInteger())
|
||||
.prefixLength(fessConfig.getQueryFuzzyPrefixLengthAsInteger())
|
||||
.transpositions(Constants.TRUE.equalsIgnoreCase(fessConfig.getQueryFuzzyTranspositions())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.apache.lucene.search.PhraseQuery;
|
|||
import org.apache.lucene.search.Query;
|
||||
import org.codelibs.fess.entity.QueryContext;
|
||||
import org.codelibs.fess.exception.InvalidQueryException;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.lastaflute.core.message.UserMessages;
|
||||
import org.opensearch.index.query.QueryBuilder;
|
||||
|
||||
|
@ -53,12 +55,13 @@ public class PhraseQueryCommand extends QueryCommand {
|
|||
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
|
||||
"Unknown phrase query: " + phraseQuery);
|
||||
}
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String field = terms[0].field();
|
||||
final String[] texts = stream(terms).get(stream -> stream.map(Term::text).toArray(n -> new String[n]));
|
||||
final String text = String.join(" ", texts);
|
||||
context.addFieldLog(field, text);
|
||||
stream(texts).of(stream -> stream.forEach(t -> context.addHighlightedQuery(t)));
|
||||
return buildDefaultQueryBuilder((f, b) -> buildMatchPhraseQuery(f, text).boost(b * boost));
|
||||
return buildDefaultQueryBuilder(fessConfig, context, (f, b) -> buildMatchPhraseQuery(f, text).boost(b * boost));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class PrefixQueryCommand extends QueryCommand {
|
|||
final String field = getSearchField(context.getDefaultField(), prefixQuery.getField());
|
||||
if (Constants.DEFAULT_FIELD.equals(field)) {
|
||||
context.addFieldLog(field, prefixQuery.getPrefix().text());
|
||||
return buildDefaultQueryBuilder(
|
||||
return buildDefaultQueryBuilder(fessConfig, context,
|
||||
(f, b) -> QueryBuilders.matchPhrasePrefixQuery(f, toLowercaseWildcard(prefixQuery.getPrefix().text())).boost(b * boost)
|
||||
.maxExpansions(fessConfig.getQueryPrefixExpansionsAsInteger()).slop(fessConfig.getQueryPrefixSlopAsInteger()));
|
||||
}
|
||||
|
@ -66,8 +66,9 @@ public class PrefixQueryCommand extends QueryCommand {
|
|||
final String origQuery = toLowercaseWildcard(query);
|
||||
context.addFieldLog(Constants.DEFAULT_FIELD, query + "*");
|
||||
context.addHighlightedQuery(origQuery);
|
||||
return buildDefaultQueryBuilder((f, b) -> QueryBuilders.matchPhrasePrefixQuery(f, origQuery).boost(b * boost)
|
||||
.maxExpansions(fessConfig.getQueryPrefixExpansionsAsInteger()).slop(fessConfig.getQueryPrefixSlopAsInteger()));
|
||||
return buildDefaultQueryBuilder(fessConfig, context,
|
||||
(f, b) -> QueryBuilders.matchPhrasePrefixQuery(f, origQuery).boost(b * boost)
|
||||
.maxExpansions(fessConfig.getQueryPrefixExpansionsAsInteger()).slop(fessConfig.getQueryPrefixSlopAsInteger()));
|
||||
}
|
||||
context.addFieldLog(field, prefixQuery.getPrefix().text() + "*");
|
||||
if (getQueryFieldConfig().notAnalyzedFieldSet.contains(field)) {
|
||||
|
|
|
@ -72,9 +72,9 @@ public abstract class QueryCommand {
|
|||
(String[]) request.getAttribute(Constants.REQUEST_LANGUAGES)));
|
||||
}
|
||||
|
||||
protected BoolQueryBuilder buildDefaultQueryBuilder(final DefaultQueryBuilderFunction builder) {
|
||||
protected BoolQueryBuilder buildDefaultQueryBuilder(final FessConfig fessConfig, final QueryContext context,
|
||||
final DefaultQueryBuilderFunction builder) {
|
||||
final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
boolQuery.should(builder.apply(fessConfig.getIndexFieldTitle(), fessConfig.getQueryBoostTitleAsDecimal().floatValue()));
|
||||
boolQuery.should(builder.apply(fessConfig.getIndexFieldContent(), fessConfig.getQueryBoostContentAsDecimal().floatValue()));
|
||||
final float importantContentBoost = fessConfig.getQueryBoostImportantContentAsDecimal().floatValue();
|
||||
|
|
|
@ -15,9 +15,13 @@
|
|||
*/
|
||||
package org.codelibs.fess.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.search.Query;
|
||||
|
@ -31,13 +35,17 @@ public class QueryProcessor {
|
|||
|
||||
protected Map<String, QueryCommand> queryCommandMap = new HashMap<>();
|
||||
|
||||
protected List<Filter> filterList = new ArrayList<>();
|
||||
|
||||
protected FilterChain filterChain;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
createFilterChain();
|
||||
}
|
||||
|
||||
public QueryBuilder execute(final QueryContext context, final Query query, final float boost) {
|
||||
final QueryCommand queryCommand = queryCommandMap.get(query.getClass().getSimpleName());
|
||||
if (queryCommand != null) {
|
||||
return queryCommand.execute(context, query, boost);
|
||||
}
|
||||
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
|
||||
"Unknown q: " + query.getClass() + " => " + query);
|
||||
return filterChain.execute(context, query, boost);
|
||||
}
|
||||
|
||||
public void add(final String name, final QueryCommand queryCommand) {
|
||||
|
@ -49,4 +57,41 @@ public class QueryProcessor {
|
|||
}
|
||||
queryCommandMap.put(name, queryCommand);
|
||||
}
|
||||
|
||||
protected 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 (context, query, boost) -> filter.execute(context, query, boost, chain);
|
||||
}
|
||||
|
||||
protected FilterChain createDefaultFilterChain() {
|
||||
return (context, query, boost) -> {
|
||||
final QueryCommand queryCommand = queryCommandMap.get(query.getClass().getSimpleName());
|
||||
if (queryCommand != null) {
|
||||
return queryCommand.execute(context, query, boost);
|
||||
}
|
||||
throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryUnknown(UserMessages.GLOBAL_PROPERTY_KEY),
|
||||
"Unknown q: " + query.getClass() + " => " + query);
|
||||
};
|
||||
}
|
||||
|
||||
protected interface Filter {
|
||||
QueryBuilder execute(final QueryContext context, final Query query, final float boost, final FilterChain chain);
|
||||
|
||||
}
|
||||
|
||||
protected interface FilterChain {
|
||||
QueryBuilder execute(final QueryContext context, final Query query, final float boost);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,7 +158,8 @@ public class TermQueryCommand extends QueryCommand {
|
|||
final float boost, final String field, final String text) {
|
||||
context.addFieldLog(field, text);
|
||||
context.addHighlightedQuery(text);
|
||||
final BoolQueryBuilder boolQuery = buildDefaultQueryBuilder((f, b) -> buildMatchPhraseQuery(f, text).boost(b * boost));
|
||||
final BoolQueryBuilder boolQuery =
|
||||
buildDefaultQueryBuilder(fessConfig, context, (f, b) -> buildMatchPhraseQuery(f, text).boost(b * boost));
|
||||
final Integer fuzzyMinLength = fessConfig.getQueryBoostFuzzyMinLengthAsInteger();
|
||||
if (fuzzyMinLength >= 0 && text.length() >= fuzzyMinLength) {
|
||||
boolQuery.should(QueryBuilders.fuzzyQuery(fessConfig.getIndexFieldTitle(), text)
|
||||
|
|
|
@ -23,6 +23,8 @@ import org.apache.lucene.util.BytesRef;
|
|||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.entity.QueryContext;
|
||||
import org.codelibs.fess.exception.InvalidQueryException;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.lastaflute.core.message.UserMessages;
|
||||
import org.opensearch.index.query.QueryBuilder;
|
||||
import org.opensearch.index.query.QueryBuilders;
|
||||
|
@ -49,12 +51,13 @@ public class TermRangeQueryCommand extends QueryCommand {
|
|||
}
|
||||
|
||||
protected QueryBuilder convertTermRangeQuery(final QueryContext context, final TermRangeQuery termRangeQuery, final float boost) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String field = getSearchField(context.getDefaultField(), termRangeQuery.getField());
|
||||
if (!isSearchField(field)) {
|
||||
final String origQuery = termRangeQuery.toString();
|
||||
context.addFieldLog(Constants.DEFAULT_FIELD, origQuery);
|
||||
context.addHighlightedQuery(origQuery);
|
||||
return buildDefaultQueryBuilder((f, b) -> QueryBuilders.matchPhraseQuery(f, origQuery).boost(b));
|
||||
return buildDefaultQueryBuilder(fessConfig, context, (f, b) -> QueryBuilders.matchPhraseQuery(f, origQuery).boost(b));
|
||||
}
|
||||
context.addFieldLog(field, termRangeQuery.toString(field));
|
||||
final RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(field);
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.apache.lucene.search.WildcardQuery;
|
|||
import org.codelibs.fess.Constants;
|
||||
import org.codelibs.fess.entity.QueryContext;
|
||||
import org.codelibs.fess.exception.InvalidQueryException;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.lastaflute.core.message.UserMessages;
|
||||
import org.opensearch.index.query.QueryBuilder;
|
||||
import org.opensearch.index.query.QueryBuilders;
|
||||
|
@ -51,10 +53,11 @@ public class WildcardQueryCommand extends QueryCommand {
|
|||
}
|
||||
|
||||
protected QueryBuilder convertWildcardQuery(final QueryContext context, final WildcardQuery wildcardQuery, final float boost) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String field = getSearchField(context.getDefaultField(), wildcardQuery.getField());
|
||||
if (Constants.DEFAULT_FIELD.equals(field)) {
|
||||
context.addFieldLog(field, wildcardQuery.getTerm().text());
|
||||
return buildDefaultQueryBuilder(
|
||||
return buildDefaultQueryBuilder(fessConfig, context,
|
||||
(f, b) -> QueryBuilders.wildcardQuery(f, toLowercaseWildcard(wildcardQuery.getTerm().text())).boost(b * boost));
|
||||
}
|
||||
if (isSearchField(field)) {
|
||||
|
@ -65,7 +68,7 @@ public class WildcardQueryCommand extends QueryCommand {
|
|||
final String origQuery = "*" + toLowercaseWildcard(query) + "*";
|
||||
context.addFieldLog(Constants.DEFAULT_FIELD, origQuery);
|
||||
context.addHighlightedQuery(query);
|
||||
return buildDefaultQueryBuilder((f, b) -> QueryBuilders.wildcardQuery(f, origQuery).boost(b * boost));
|
||||
return buildDefaultQueryBuilder(fessConfig, context, (f, b) -> QueryBuilders.wildcardQuery(f, origQuery).boost(b * boost));
|
||||
}
|
||||
|
||||
protected String toLowercaseWildcard(final String value) {
|
||||
|
|
|
@ -71,7 +71,9 @@ public class QueryHelperTest extends UnitFessTestCase {
|
|||
queryFieldConfig = new QueryFieldConfig();
|
||||
ComponentUtil.register(queryFieldConfig, "queryFieldConfig");
|
||||
queryFieldConfig.init();
|
||||
ComponentUtil.register(new QueryProcessor(), "queryProcessor");
|
||||
QueryProcessor queryProcessor = new QueryProcessor();
|
||||
ComponentUtil.register(queryProcessor, "queryProcessor");
|
||||
queryProcessor.init();
|
||||
new BooleanQueryCommand().register();
|
||||
new BoostQueryCommand().register();
|
||||
new FuzzyQueryCommand().register();
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 2012-2022 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;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.codelibs.fess.entity.QueryContext;
|
||||
import org.codelibs.fess.query.QueryProcessor.FilterChain;
|
||||
import org.codelibs.fess.unit.UnitFessTestCase;
|
||||
import org.opensearch.index.query.BoolQueryBuilder;
|
||||
import org.opensearch.index.query.QueryBuilder;
|
||||
import org.opensearch.index.query.QueryBuilders;
|
||||
|
||||
public class QueryProcessorTest extends UnitFessTestCase {
|
||||
|
||||
public void test_executeWithFilter() {
|
||||
final AtomicBoolean called = new AtomicBoolean(false);
|
||||
QueryProcessor queryProcessor = new QueryProcessor() {
|
||||
protected FilterChain createDefaultFilterChain() {
|
||||
return (context, query, boost) -> {
|
||||
called.set(true);
|
||||
return QueryBuilders.boolQuery();
|
||||
};
|
||||
}
|
||||
};
|
||||
queryProcessor.init();
|
||||
|
||||
QueryContext context = new QueryContext(null, false);
|
||||
MatchAllDocsQuery query = new MatchAllDocsQuery();
|
||||
|
||||
QueryBuilder queryBuilder = queryProcessor.execute(context, query, 1.0f);
|
||||
assertTrue(called.get());
|
||||
assertEquals(BoolQueryBuilder.class, queryBuilder.getClass());
|
||||
|
||||
called.set(false);
|
||||
final AtomicBoolean calledFirst = new AtomicBoolean(false);
|
||||
queryProcessor.addFilter(new QueryProcessor.Filter() {
|
||||
@Override
|
||||
public QueryBuilder execute(QueryContext context, Query query, float boost, FilterChain chain) {
|
||||
calledFirst.set(true);
|
||||
assertFalse(called.get());
|
||||
QueryBuilder builder = chain.execute(context, query, boost);
|
||||
assertTrue(called.get());
|
||||
return builder;
|
||||
}
|
||||
});
|
||||
queryBuilder = queryProcessor.execute(context, query, 1.0f);
|
||||
assertTrue(called.get());
|
||||
assertTrue(calledFirst.get());
|
||||
assertEquals(BoolQueryBuilder.class, queryBuilder.getClass());
|
||||
|
||||
called.set(false);
|
||||
calledFirst.set(false);
|
||||
final AtomicBoolean calledSecond = new AtomicBoolean(false);
|
||||
queryProcessor.addFilter(new QueryProcessor.Filter() {
|
||||
@Override
|
||||
public QueryBuilder execute(QueryContext context, Query query, float boost, FilterChain chain) {
|
||||
calledSecond.set(true);
|
||||
assertFalse(called.get());
|
||||
assertFalse(calledFirst.get());
|
||||
QueryBuilder builder = chain.execute(context, query, boost);
|
||||
assertTrue(called.get());
|
||||
assertTrue(calledFirst.get());
|
||||
return builder;
|
||||
}
|
||||
});
|
||||
queryBuilder = queryProcessor.execute(context, query, 1.0f);
|
||||
assertTrue(called.get());
|
||||
assertTrue(calledFirst.get());
|
||||
assertTrue(calledSecond.get());
|
||||
assertEquals(BoolQueryBuilder.class, queryBuilder.getClass());
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue