querqy.rewrite.commonrules.CommonRulesRewriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of querqy-core Show documentation
Show all versions of querqy-core Show documentation
Querqy library for query rewriting: Querqy Core
/**
*
*/
package querqy.rewrite.commonrules;
import querqy.infologging.InfoLoggingContext;
import querqy.model.*;
import querqy.model.Term;
import querqy.rewrite.ContextAwareQueryRewriter;
import querqy.rewrite.SearchEngineRequestAdapter;
import querqy.rewrite.commonrules.model.*;
import querqy.rewrite.commonrules.model.InputBoundary.Type;
import querqy.rewrite.commonrules.select.SelectionStrategy;
import querqy.rewrite.commonrules.select.TopRewritingActionCollector;
import java.util.*;
/**
* @author rene
*
*/
public class CommonRulesRewriter extends AbstractNodeVisitor implements ContextAwareQueryRewriter {
static final InputBoundary LEFT_BOUNDARY = new InputBoundary(Type.LEFT);
static final InputBoundary RIGHT_BOUNDARY = new InputBoundary(Type.RIGHT);
public static final String APPLIED_RULES = "APPLIED_RULES";
protected final RulesCollection rules;
protected final LinkedList> sequencesStack;
protected ExpandedQuery expandedQuery;
protected SearchEngineRequestAdapter searchEngineRequestAdapter;
protected SelectionStrategy selectionStrategy;
public CommonRulesRewriter(final RulesCollection rules, final SelectionStrategy selectionStrategy) {
this.rules = rules;
sequencesStack = new LinkedList<>();
this.selectionStrategy = selectionStrategy;
}
@Override
public ExpandedQuery rewrite(ExpandedQuery query) {
throw new UnsupportedOperationException("This rewriter needs a query context");
}
@Override
public ExpandedQuery rewrite(ExpandedQuery query, Map context) {
throw new UnsupportedOperationException("This rewriter needs a query adapter");
}
@Override
public ExpandedQuery rewrite(ExpandedQuery query, SearchEngineRequestAdapter searchEngineRequestAdapter) {
QuerqyQuery> userQuery = query.getUserQuery();
if (userQuery instanceof Query) {
this.expandedQuery = query;
this.searchEngineRequestAdapter = searchEngineRequestAdapter;
sequencesStack.add(new PositionSequence<>());
super.visit((BooleanQuery) query.getUserQuery());
applySequence(sequencesStack.removeLast(), true);
if (((Query) userQuery).isEmpty()
&& (query.getBoostUpQueries() != null || query.getFilterQueries() != null)) {
query.setUserQuery(new MatchAllQuery(true));
}
}
return query;
}
@Override
public Node visit(BooleanQuery booleanQuery) {
sequencesStack.add(new PositionSequence<>());
super.visit(booleanQuery);
applySequence(sequencesStack.removeLast(), false);
return null;
}
protected void applySequence(final PositionSequence sequence, boolean addBoundaries) {
final PositionSequence sequenceForLookUp = addBoundaries
? addBoundaries(sequence) : termSequenceToInputSequence(sequence);
final boolean isDebug = Boolean.TRUE.equals(searchEngineRequestAdapter.getContext().get(CONTEXT_KEY_DEBUG_ENABLED));
List actionsDebugInfo = (List) searchEngineRequestAdapter.getContext().get(CONTEXT_KEY_DEBUG_DATA);
// prepare debug info context object if requested
if (isDebug && actionsDebugInfo == null) {
actionsDebugInfo = new LinkedList<>();
searchEngineRequestAdapter.getContext().put(CONTEXT_KEY_DEBUG_DATA, actionsDebugInfo);
}
final TopRewritingActionCollector collector = selectionStrategy.createTopRewritingActionCollector();
rules.collectRewriteActions(sequenceForLookUp, collector);
final List actions = collector.createActions();
final InfoLoggingContext infoLoggingContext = searchEngineRequestAdapter.getInfoLoggingContext().orElse(null);
final boolean infoLoggingEnabled = infoLoggingContext != null && infoLoggingContext.isEnabledForRewriter();
final Set appliedRules = infoLoggingEnabled ? new HashSet<>() : null;
for (Action action : actions) {
if (isDebug) {
actionsDebugInfo.add(action.toString());
}
final Instructions instructions = action.getInstructions();
instructions.forEach(instruction ->
instruction.apply(sequence, action.getTermMatches(),
action.getStartPosition(),
action.getEndPosition(), expandedQuery, searchEngineRequestAdapter)
);
if (infoLoggingEnabled) {
instructions.getProperty(Instructions.StandardPropertyNames.LOG_MESSAGE)
.map(String::valueOf).ifPresent(appliedRules::add);
}
}
if (infoLoggingEnabled && !appliedRules.isEmpty()) {
final Map> message = new IdentityHashMap<>(1);
message.put(APPLIED_RULES, appliedRules);
infoLoggingContext.log(message);
}
}
protected PositionSequence termSequenceToInputSequence(PositionSequence sequence) {
PositionSequence result = new PositionSequence<>();
for (List termList : sequence) {
result.add(Collections.unmodifiableList(termList));
}
return result;
}
protected PositionSequence addBoundaries(PositionSequence sequence) {
PositionSequence result = new PositionSequence<>();
result.nextPosition();
result.addElement(LEFT_BOUNDARY);
for (List termList : sequence) {
result.add(Collections.unmodifiableList(termList));
}
result.nextPosition();
result.addElement(RIGHT_BOUNDARY);
return result;
}
@Override
public Node visit(DisjunctionMaxQuery disjunctionMaxQuery) {
sequencesStack.getLast().nextPosition();
return super.visit(disjunctionMaxQuery);
}
@Override
public Node visit(Term term) {
sequencesStack.getLast().addElement(term);
return super.visit(term);
}
}