use of org.apache.lucene.queries.function.FunctionQuery in project lucene-solr by apache.
the class BoostQParserPlugin method createParser.
@Override
public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
return new QParser(qstr, localParams, params, req) {
QParser baseParser;
ValueSource vs;
String b;
@Override
public Query parse() throws SyntaxError {
b = localParams.get(BOOSTFUNC);
baseParser = subQuery(localParams.get(QueryParsing.V), null);
Query q = baseParser.getQuery();
if (b == null)
return q;
Query bq = subQuery(b, FunctionQParserPlugin.NAME).getQuery();
if (bq instanceof FunctionQuery) {
vs = ((FunctionQuery) bq).getValueSource();
} else {
vs = new QueryValueSource(bq, 0.0f);
}
return new BoostedQuery(q, vs);
}
@Override
public String[] getDefaultHighlightFields() {
return baseParser.getDefaultHighlightFields();
}
@Override
public Query getHighlightQuery() throws SyntaxError {
return baseParser.getHighlightQuery();
}
@Override
public void addDebugInfo(NamedList<Object> debugInfo) {
// encapsulate base debug info in a sub-list?
baseParser.addDebugInfo(debugInfo);
debugInfo.add("boost_str", b);
debugInfo.add("boost_parsed", vs);
}
};
}
use of org.apache.lucene.queries.function.FunctionQuery in project ddf by codice.
the class GeoNamesQueryLuceneIndex method createQuery.
protected Query createQuery(final String queryString) throws ParseException {
final StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
final QueryParser nameQueryParser = new QueryParser(GeoNamesLuceneConstants.NAME_FIELD, standardAnalyzer);
nameQueryParser.setEnablePositionIncrements(false);
/* For the name, we construct a query searching for exactly the query string (the phrase
query), a query searching for all the terms in the query string (the AND query), and a
query searching for any of the terms in the query string (the OR query). We take the
maximum of the scores generated by these three queries and use that as the score for the
name. */
// Surround with quotes so Lucene looks for the words in the query as a phrase.
// Phrase query gets the biggest boost - 3.2 was obtained after some experimentation.
final Query phraseNameQuery = new BoostQuery(nameQueryParser.parse("\"" + queryString + "\""), 3.2f);
// By default, QueryParser uses OR to separate terms.
// We give OR queries the lowest boost because they're not as good as phrase matches or
// AND matches - 1 (the default boost value) was obtained after some experimentation.
final Query orNameQuery = nameQueryParser.parse(queryString);
nameQueryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
// We give AND queries the second-biggest boost because they're better than OR matches but
// not as good as phrase matches - 2 was obtained after some experimentation.
final Query andNameQuery = new BoostQuery(nameQueryParser.parse(queryString), 2f);
final List<Query> nameQueryList = Arrays.asList(phraseNameQuery, orNameQuery, andNameQuery);
// This query will score each document by the maximum of the three sub-queries.
final Query nameQuery = new DisjunctionMaxQuery(nameQueryList, 0);
final QueryParser alternateNamesQueryParser = new QueryParser(GeoNamesLuceneConstants.ALTERNATE_NAMES_FIELD, standardAnalyzer);
// For the alternate names, we perform an AND query and an OR query, both of which are
// boosted less than the name query because the alternate names are generally not as
// important.
// The OR query gets a lower boost - 0.5 was obtained after some experimentation.
final Query orAlternateNamesQuery = new BoostQuery(alternateNamesQueryParser.parse(queryString), 0.5f);
alternateNamesQueryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
// The AND query gets a higher boost - 1 (the default boost value) was obtained after some
// experimentation.
final Query andAlternateNamesQuery = alternateNamesQueryParser.parse(queryString);
final List<Query> alternateNamesQueryList = Arrays.asList(orAlternateNamesQuery, andAlternateNamesQuery);
// This query will score each document by the maximum of the two sub-queries.
final Query alternateNamesQuery = new DisjunctionMaxQuery(alternateNamesQueryList, 0);
final List<Query> queryList = Arrays.asList(nameQuery, alternateNamesQuery);
// This query will score each document by the sum of the two sub-queries, since both the
// name and the alternate names are important.
// The boost values ensure that how well the query matches the name has a bigger impact on
// the final score than how well it matches the alternate names.
final DisjunctionMaxQuery disjunctionMaxQuery = new DisjunctionMaxQuery(queryList, 1.0f);
// This is the boost we calculated at index time, and it is applied in the CustomScoreQuery.
final FunctionQuery boostQuery = new FunctionQuery(new FloatFieldSource(GeoNamesLuceneConstants.BOOST_FIELD));
return new CustomScoreQuery(disjunctionMaxQuery, boostQuery);
}
use of org.apache.lucene.queries.function.FunctionQuery in project lucene-solr by apache.
the class TestOrdValues method doTestRank.
// Test that queries based on reverse/ordFieldScore scores correctly
private void doTestRank(String field, boolean inOrder) throws Exception {
IndexReader r = DirectoryReader.open(dir);
IndexSearcher s = newSearcher(r);
ValueSource vs;
if (inOrder) {
vs = new OrdFieldSource(field);
} else {
vs = new ReverseOrdFieldSource(field);
}
Query q = new FunctionQuery(vs);
log("test: " + q);
QueryUtils.check(random(), q, s);
ScoreDoc[] h = s.search(q, 1000).scoreDocs;
assertEquals("All docs should be matched!", N_DOCS, h.length);
String prevID = inOrder ? // greater than all ids of docs in this test ("ID0001", etc.)
"IE" : // smaller than all ids of docs in this test ("ID0001", etc.)
"IC";
for (int i = 0; i < h.length; i++) {
String resID = s.doc(h[i].doc).get(ID_FIELD);
log(i + ". score=" + h[i].score + " - " + resID);
log(s.explain(q, h[i].doc));
if (inOrder) {
assertTrue("res id " + resID + " should be < prev res id " + prevID, resID.compareTo(prevID) < 0);
} else {
assertTrue("res id " + resID + " should be > prev res id " + prevID, resID.compareTo(prevID) > 0);
}
prevID = resID;
}
r.close();
}
use of org.apache.lucene.queries.function.FunctionQuery in project lucene-solr by apache.
the class FunctionQParser method parseValueSource.
protected ValueSource parseValueSource(int flags) throws SyntaxError {
ValueSource valueSource;
int ch = sp.peek();
if (ch >= '0' && ch <= '9' || ch == '.' || ch == '+' || ch == '-') {
Number num = sp.getNumber();
if (num instanceof Long) {
valueSource = new LongConstValueSource(num.longValue());
} else if (num instanceof Double) {
valueSource = new DoubleConstValueSource(num.doubleValue());
} else {
// shouldn't happen
valueSource = new ConstValueSource(num.floatValue());
}
} else if (ch == '"' || ch == '\'') {
valueSource = new LiteralValueSource(sp.getQuotedString());
} else if (ch == '$') {
sp.pos++;
String param = sp.getId();
String val = getParam(param);
if (val == null) {
throw new SyntaxError("Missing param " + param + " while parsing function '" + sp.val + "'");
}
QParser subParser = subQuery(val, "func");
if (subParser instanceof FunctionQParser) {
((FunctionQParser) subParser).setParseMultipleSources(true);
}
Query subQuery = subParser.getQuery();
if (subQuery instanceof FunctionQuery) {
valueSource = ((FunctionQuery) subQuery).getValueSource();
} else {
valueSource = new QueryValueSource(subQuery, 0.0f);
}
/***
// dereference *simple* argument (i.e., can't currently be a function)
// In the future we could support full function dereferencing via a stack of ValueSource (or StringParser) objects
ch = val.length()==0 ? '\0' : val.charAt(0);
if (ch>='0' && ch<='9' || ch=='.' || ch=='+' || ch=='-') {
StrParser sp = new StrParser(val);
Number num = sp.getNumber();
if (num instanceof Long) {
valueSource = new LongConstValueSource(num.longValue());
} else if (num instanceof Double) {
valueSource = new DoubleConstValueSource(num.doubleValue());
} else {
// shouldn't happen
valueSource = new ConstValueSource(num.floatValue());
}
} else if (ch == '"' || ch == '\'') {
StrParser sp = new StrParser(val);
val = sp.getQuotedString();
valueSource = new LiteralValueSource(val);
} else {
if (val.length()==0) {
valueSource = new LiteralValueSource(val);
} else {
String id = val;
SchemaField f = req.getSchema().getField(id);
valueSource = f.getType().getValueSource(f, this);
}
}
***/
} else {
String id = sp.getId();
if (sp.opt("(")) {
// a function... look it up.
ValueSourceParser argParser = req.getCore().getValueSourceParser(id);
if (argParser == null) {
throw new SyntaxError("Unknown function " + id + " in FunctionQuery(" + sp + ")");
}
valueSource = argParser.parse(this);
sp.expect(")");
} else {
if ("true".equals(id)) {
valueSource = new BoolConstValueSource(true);
} else if ("false".equals(id)) {
valueSource = new BoolConstValueSource(false);
} else {
SchemaField f = req.getSchema().getField(id);
valueSource = f.getType().getValueSource(f, this);
}
}
}
if ((flags & FLAG_CONSUME_DELIMITER) != 0) {
consumeArgumentDelimiter();
}
return valueSource;
}
use of org.apache.lucene.queries.function.FunctionQuery in project lucene-solr by apache.
the class FunctionQParser method parse.
@Override
public Query parse() throws SyntaxError {
ValueSource vs = null;
List<ValueSource> lst = null;
for (; ; ) {
ValueSource valsource = parseValueSource(FLAG_DEFAULT & ~FLAG_CONSUME_DELIMITER);
sp.eatws();
if (!parseMultipleSources) {
vs = valsource;
break;
} else {
if (lst != null) {
lst.add(valsource);
} else {
vs = valsource;
}
}
// check if there is a "," separator
if (sp.peek() != ',')
break;
consumeArgumentDelimiter();
if (lst == null) {
lst = new ArrayList<>(2);
lst.add(valsource);
}
}
if (parseToEnd && sp.pos < sp.end) {
throw new SyntaxError("Unexpected text after function: " + sp.val.substring(sp.pos, sp.end));
}
if (lst != null) {
vs = new VectorValueSource(lst);
}
return new FunctionQuery(vs);
}
Aggregations