package org.apache.lucene.queryparser.flexible.aqp.processors; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.lucene.queryparser.flexible.aqp.builders.AqpFunctionQueryBuilder; import org.apache.lucene.queryparser.flexible.aqp.config.AqpAdsabsQueryConfigHandler; import org.apache.lucene.queryparser.flexible.aqp.nodes.AqpFunctionQueryNode; import org.apache.lucene.queryparser.flexible.aqp.nodes.AqpWhiteSpacedQueryNode; import org.apache.lucene.queryparser.flexible.aqp.parser.AqpStandardQueryConfigHandler; import org.apache.lucene.queryparser.flexible.aqp.processors.AqpQProcessor.OriginalInput; import org.apache.lucene.queryparser.flexible.core.QueryNodeException; import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler; import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages; import org.apache.lucene.queryparser.flexible.core.nodes.BoostQueryNode; import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode; import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode; import org.apache.lucene.queryparser.flexible.core.nodes.SlopQueryNode; import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor; import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl; import org.apache.lucene.queryparser.flexible.messages.MessageImpl; /** * This processor looks for {@link AqpWhiteSpacedQueryNode} * and builds a {@link AqpFunctionQueryNode} out of it. * This is the solution for unfielded search. * * Your config should specify: * * aqp.unfielded.tokens.function.name - name of the function * that receives the input {@link AqpFunctionQueryNode} */ public class AqpWhiteSpacedQueryNodeProcessor extends QueryNodeProcessorImpl implements QueryNodeProcessor { @Override protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException { if (node instanceof AqpWhiteSpacedQueryNode) { QueryConfigHandler config = getQueryConfigHandler(); if (!config.has(AqpAdsabsQueryConfigHandler.ConfigurationKeys.FUNCTION_QUERY_BUILDER_CONFIG)) { throw new QueryNodeException(new MessageImpl( "Invalid configuration", "Missing FunctionQueryBuilder provider")); } String funcName = getFuncName(); String subQuery = ((FieldQueryNode) node).getTextAsString(); String field = ((FieldQueryNode) node).getFieldAsString(); if (field.equals(config.get(AqpAdsabsQueryConfigHandler.ConfigurationKeys.UNFIELDED_SEARCH_FIELD))) { field = null; } if (field != null) { subQuery = field + ":" + subQuery; } if (node.getParent() instanceof SlopQueryNode) { subQuery = "(" + subQuery + ")"; subQuery = subQuery + "~" + ((SlopQueryNode) node.getParent()).getValue(); if (node.getParent().getParent() instanceof BoostQueryNode) { subQuery = subQuery + "^" + ((BoostQueryNode) node.getParent().getParent()).getValue(); } } else if (node.getParent() instanceof BoostQueryNode) { subQuery = "(" + subQuery + ")"; subQuery = subQuery + "^" + ((BoostQueryNode) node.getParent()).getValue(); } node.setTag("subQuery", subQuery); AqpFunctionQueryBuilder builder = config.get(AqpAdsabsQueryConfigHandler.ConfigurationKeys.FUNCTION_QUERY_BUILDER_CONFIG) .getBuilder(funcName, (QueryNode) node, config); if (builder == null) { throw new QueryNodeException(new MessageImpl(QueryParserMessages.INVALID_SYNTAX, "Unknown function: \"" + funcName +"\"" )); } List<OriginalInput> fValues = new ArrayList<OriginalInput>(); fValues.add(new OriginalInput(subQuery, ((AqpWhiteSpacedQueryNode) node).getBegin(), ((AqpWhiteSpacedQueryNode) node).getEnd())); return new AqpFunctionQueryNode(funcName, builder, fValues); } return node; } @Override protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException { return node; } @Override protected List<QueryNode> setChildrenOrder(List<QueryNode> children) throws QueryNodeException { return children; } private String getFuncName() { String key = "aqp.unfielded.tokens.function.name"; Map<String, String> args = getQueryConfigHandler().get( AqpStandardQueryConfigHandler.ConfigurationKeys.NAMED_PARAMETER); if (args.containsKey(key)) { return args.get(key); } return "edismax_combined_aqp"; } }