javasolrsolrjsolr5

How to properly use a scoring function in Solrj


I'm trying to boost the score of a document according to the value of a floating number field from the document.

For example, the user may search for "Oliphaunts named ron, with height between 6 and 10 meters" and I'd like to query the height field in a manner akin to a DecayFunction.

In the following simplified query I expect to retrieve oliphaunts scored by name and height, where height closer to 8 meters is better -

q=name:"ron" _val_:"div(1,abs(sub(height,8)))"

I've drafted my exponential-decay scoring function using a combination of math operands and regular functions -

exp(sub(0,div(pow(max(0,sub(abs(sub(value,origin)),offset)),2),mul(2,sub(0,div(pow(scale,2),mul(2,ln(decay))))))))

Now I'd like to incorporate this function into the query score using the _val_ magic field.

How can I accomplish this in Solrj?

What other ways are there (instead of _val_) to do this?

{p.s. - I'm using the standard query parser, in Solr 5.3.1}


Solution

  • I ended up Accomplishing this by implementing a custom lucene.search.Query. The following is a summary of the class and its usage -

    package org.example.ronvisbord.solr.queries.custom;
    
    import org.apache.lucene.search.Query;
    
    public class HeightFunctionQuery extends Query {
    
        private final String queryTemplate = "(_val_:\"%s\")^%f";
        private final String functionTemplate = "div(1,abs(sub(%s,%d)))";
        private double boost;
    
        @Override
        public String toString(String field) {
            return String.format(queryTemplate, createFunction(field), boost);
        }
    
        public HeightFunctionQuery(double boost, int targetHeight) {
            this.boost = boost;
            this.targetHeight = targetHeight;
        }
    
        private String createFunction(String field) {
            return String.format(functionTemplate, field, targetHeight);
        }
    }
    

    I used the class by putting its toString(field) in the "q" parameter of a solrj.SolrQuery -

    import org.apache.solr.client.solrj.impl.HttpSolrClient;
    import org.apache.solr.client.solrj.SolrClient;
    import org.example.ronvisbord.solr.queries.custom.HeightFunctionQuery;
    import org.apache.lucene.search.Query;
    import org.apache.solr.client.solrj.SolrQuery;
    import org.apache.solr.client.solrj.SolrRequest;
    import org.apache.solr.client.solrj.response.QueryResponse;
    
    ...
    
        double boost = 10.0;
        double targetHeight = 8;
        String heightField = "height";
    
        Query heightQuery = new HeightFunctionQuery(targetHeight, boost);
        SolrQuery solrQuery = new SolrQuery();
        solrQuery.set("q", heightQuery.toString(heightField));
        // ... further configure the solrQuery ...
    
        SolrClient client = new HttpSolrClient("http://solr_host:8983/solr/core")
        QueryResponse response = client.query(query, SolrRequest.METHOD.POST)
        // ... process results ...