This guide demonstrates how to deploy a searcher
implementing a last stage of phased ranking. The searcher re-ranks the
global top 200 documents which have been ranked by the content nodes using the configurable ranking
specification in the document schema(s).
Matching query protocol phase: The matching protocol phase which asks each content node involved in the query
to return the locally best ranking hits (ranked by the configurable ranking expressions defined in the schema).
This matching query protocol phase can include several ranking phases which are executed per content node.
In the query protocol phase the content nodes can also return match-features which
a re-ranking searcher can use to re-rank results (or feature logging).
In the custom searcher one is working on the global best ranking hits from the content nodes, and
can have access to aggregated features which is calculated across the top-ranking documents (the global best documents).
Fill query protocol phase: Fill summary data for the global top ranking hits after all ranking phases.
If one needs access to the document fields,
the searcher would need to call execution.fill before the re-ranking logic,
this would then cost more resources
than just using match-features which is delivered in the first protocol matching phase.
If one needs access to a subset of fields during stateless re-ranking,
consider configuring a dedicated document summary.
Start by defining a simple schema with two fields.
We also define a rank profile with two rank features
to be used in the searcher for re-ranking:
schemadoc{documentdoc{field name typestring{indexing:summary|indexmatch: textindex:enable-bm25}field downloads typeint{indexing:summary|attribute}}fieldset default {fields: name
}rank-profilerank-profile-with-match{first-phase{expression:bm25(name)}match-features{bm25(name)attribute(downloads)}}}
The searcher implementing the re-ranking logic:
packageai.vespa.example.searcher;importcom.yahoo.search.Query;importcom.yahoo.search.Result;importcom.yahoo.search.Searcher;importcom.yahoo.search.result.FeatureData;importcom.yahoo.search.result.Hit;importcom.yahoo.search.searchchain.Execution;publicclassReRankingSearcherextendsSearcher{@OverridepublicResultsearch(Queryquery,Executionexecution){inthits=query.getHits();query.setHits(200);//Re-ranking windowquery.getRanking().setProfile("rank-profile-with-match");Resultresult=execution.search(query);if(result.getTotalHitCount()==0||result.hits().getErrorHit()!=null)returnresult;doublemax=0;//Find max value of the windowfor(Hithit:result.hits()){FeatureDatafeatureData=(FeatureData)hit.getField("matchfeatures");if(featureData==null)thrownewRuntimeException("No 'matchfeatures' found - wrong rank profile used?");doubledownloads=featureData.getDouble("attribute(downloads)");if(downloads>max)max=downloads;}//re-rank using normalized valuefor(Hithit:result.hits()){FeatureDatafeatureData=(FeatureData)hit.getField("matchfeatures");if(featureData==null)thrownewRuntimeException("No 'matchfeatures' found - wrong rank profile used?");doubledownloads=featureData.getDouble("attribute(downloads)");doublenormalizedByMax=downloads/max;//Change medoublebm25Name=featureData.getDouble("bm25(name)");doublenewScore=bm25Name+normalizedByMax;hit.setField("rerank-score",newScore);hit.setRelevance(newScore);}result.hits().sort();//trim the result down to the requested number of hitsresult.hits().trim(0,hits);returnresult;}}
Notice the bundle name of the searcher, this needs to be in synch with the artifactId defined in pom.xml:
<?xml version="1.0"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>ai.vespa.example</groupId><artifactId>ranking</artifactId><!-- Note: When changing this, also change bundle names in services.xml --><version>1.0.0</version><packaging>container-plugin</packaging><parent><groupId>com.yahoo.vespa</groupId><artifactId>cloud-tenant-base</artifactId><version>[7,999)</version><!-- Use the latest Vespa release on each build --><relativePath/></parent><properties><bundle-plugin.failOnWarnings>true</bundle-plugin.failOnWarnings><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><test.hide>true</test.hide></properties></project>