Ho to use FunctionScoreQuery with text fields?

1.3k Views Asked by At

In Lucene 6.6.0, index-time boosting is deprecated. Moreover, also CustomQueryScore is deprecated. So, Lucene developers advice is to use FunctionScoreQuery. However, I can't understand how to boost text field with FunctionScoreQuery, since it takes as input DoubleValuesSource, which helps to boost just numerical fields (fromIntField, fromDoubleField etc...)

3

There are 3 best solutions below

3
On

I believe you are misunderstanding the guidance they are giving there. You index the boost in a docValues field, not the text. Think of the boost as sort of a meta-field. So you end up with two fields, something like:

  • a text field, myField
  • a numeric DocValues field, myFieldBoost

And you would query the contents of myField, and factor the value of myFieldBoost into your FunctionScoreQuery.

2
On

Boosting while searching is a better solution and can be done with :

For basic understanding how scoring works have a lock at the documentation

0
On

It might be too late, but check the discussions here: http://lucene.472066.n3.nabble.com/any-example-on-FunctionScoreQuery-since-Field-setBoost-is-deprecated-with-Lucene-6-6-0-td4400355.html, and some copy and paste of how to use the FunctionScoreQuery class:

Example that sorts based on an expression:

// compile an expression:
Expression expr = JavascriptCompiler.compile("sqrt(_score) + ln(popularity)");

// SimpleBindings just maps variables to SortField instances
SimpleBindings bindings = new SimpleBindings();
bindings.add(new SortField("_score", SortField.Type.SCORE));
bindings.add(new SortField("popularity", SortField.Type.INT));

// create a sort field and sort by it (reverse order)
Sort sort = new Sort(expr.getSortField(bindings, true));
Query query = new TermQuery(new Term("body", "contents"));
searcher.search(query, 10, sort);

Example that modifies the scores produced by the query:

// compile an expression:
Expression expr = JavascriptCompiler.compile("sqrt(_score) + ln(popularity)");

// SimpleBindings just maps variables to SortField instances
SimpleBindings bindings = new SimpleBindings();
bindings.add(new SortField("_score", SortField.Type.SCORE));
bindings.add(new SortField("popularity", SortField.Type.INT));

// create a query that matches based on body:contents but
// scores using expr
Query query = new FunctionScoreQuery(
    new TermQuery(new Term("body", "contents")),
    expr.getDoubleValuesSource(bindings));
searcher.search(query, 10);

The Lucene Expression class accepts Javascript expressions: (https://lucene.apache.org/core/7_7_2/expressions/org/apache/lucene/expressions/js/package-summary.html)

"A Javascript expression is a numeric expression specified using an expression syntax that's based on JavaScript expressions. You can construct expressions using:

  • Integer, floating point, hex and octal literals
  • Arithmetic operators: + - * / %
  • Bitwise operators: | & ^ ~ << >> >>>
  • Boolean operators (including the ternary operator): && || ! ?:
  • Comparison operators: < <= == >= >
  • Common mathematic functions: abs ceil exp floor ln log10 logn max min sqrt pow
  • Trigonometric library functions: acosh acos asinh asin atanh atan atan2 cosh cos sinh sin tanh tan
  • Distance functions: haversin
  • Miscellaneous functions: min, max
  • Arbitrary external variables" - see the above Bindings examples