summaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/prelude/fastsearch
diff options
context:
space:
mode:
Diffstat (limited to 'container-search/src/main/java/com/yahoo/prelude/fastsearch')
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/fastsearch/FS4SearchInvoker.java7
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java32
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java4
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java64
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java21
5 files changed, 111 insertions, 17 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FS4SearchInvoker.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FS4SearchInvoker.java
index 24653db5671..0cf6a8a8449 100644
--- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FS4SearchInvoker.java
+++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FS4SearchInvoker.java
@@ -44,13 +44,10 @@ public class FS4SearchInvoker extends SearchInvoker implements ResponseMonitor<F
}
@Override
- protected void sendSearchRequest(Query query, QueryPacket queryPacket) throws IOException {
+ protected void sendSearchRequest(Query query) throws IOException {
log.finest("sending query packet");
- if (queryPacket == null) {
- // query changed for subchannel
- queryPacket = searcher.createQueryPacket(searcher.getServerId(), query);
- }
+ var queryPacket = searcher.createQueryPacket(searcher.getServerId(), query);
this.query = query;
this.queryPacket = queryPacket;
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java
index ff719c3eadc..a06b1518a12 100644
--- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java
+++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastHit.java
@@ -5,11 +5,13 @@ import com.yahoo.data.access.ObjectTraverser;
import com.yahoo.document.GlobalId;
import com.yahoo.fs4.QueryPacketData;
import com.yahoo.net.URI;
+import com.yahoo.search.query.Sorting;
import com.yahoo.search.result.Hit;
import com.yahoo.search.result.Relevance;
import com.yahoo.data.access.Inspector;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -45,6 +47,9 @@ public class FastHit extends Hit {
private transient QueryPacketData queryPacketData = null;
+ private transient byte[] sortData = null;
+ private transient Sorting sortDataSorting = null;
+
/**
* Summaries added to this hit which are not yet decoded into fields.
* Fields are resolved by returning the first non-null value found by
@@ -148,6 +153,33 @@ public class FastHit extends Hit {
/** Returns a serial encoding of the query which produced this hit, ot null if not available. */
public QueryPacketData getQueryPacketData() { return queryPacketData; }
+ public void setSortData(byte[] data, Sorting sorting) {
+ this.sortData = data;
+ this.sortDataSorting = sorting;
+ }
+
+ public boolean hasSortData(Sorting sorting) {
+ return sortData != null && sortDataSorting != null && sortDataSorting.equals(sorting);
+ }
+
+ public static int compareSortData(FastHit left, FastHit right, Sorting sorting) {
+ if (!left.hasSortData(sorting) || !right.hasSortData(sorting)) {
+ return 0; // cannot sort
+ }
+ int i = Arrays.mismatch(left.sortData, right.sortData);
+ if (i < 0) {
+ return 0;
+ }
+ int max = Integer.min(left.sortData.length, right.sortData.length);
+ if (i >= max) {
+ return left.sortData.length - right.sortData.length;
+ }
+ int vl = (int) left.sortData[i] & 0xFF;
+ int vr = (int) right.sortData[i] & 0xFF;
+ int diff = vl - vr;
+ return diff;
+ }
+
/** For internal use */
public void addSummary(DocsumDefinition docsumDef, Inspector value) {
if (removedFields != null)
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java
index e61ed1715b6..5f6d4220dd4 100644
--- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java
+++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java
@@ -142,11 +142,11 @@ public class FastSearcher extends VespaBackEndSearcher {
}
@Override
- public Result doSearch2(Query query, QueryPacket queryPacket, Execution execution) {
+ public Result doSearch2(Query query, Execution execution) {
if (dispatcher.searchCluster().groupSize() == 1)
forceSinglePassGrouping(query);
try(SearchInvoker invoker = getSearchInvoker(query)) {
- Result result = invoker.search(query, queryPacket, execution);
+ Result result = invoker.search(query, execution);
if (query.properties().getBoolean(Ranking.RANKFEATURES, false)) {
// There is currently no correct choice for which
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java
new file mode 100644
index 00000000000..e87c94fa3be
--- /dev/null
+++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/SortDataHitSorter.java
@@ -0,0 +1,64 @@
+// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.prelude.fastsearch;
+
+import com.yahoo.search.query.Sorting;
+import com.yahoo.search.result.Hit;
+import com.yahoo.search.result.HitGroup;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class SortDataHitSorter {
+ public static void sort(HitGroup hitGroup, List<Hit> hits) {
+ var sorting = hitGroup.getQuery().getRanking().getSorting();
+ var fallbackOrderer = hitGroup.getOrderer();
+ if (sorting == null || fallbackOrderer == null) {
+ return;
+ }
+ var fallbackComparator = fallbackOrderer.getComparator();
+ Collections.sort(hits, getComparator(sorting, fallbackComparator));
+ }
+
+ public static boolean isSortable(Hit hit, HitGroup hitGroup) {
+ if (hitGroup.getQuery() == null) {
+ return false;
+ }
+ if (hit instanceof FastHit) {
+ var fhit = (FastHit) hit;
+ return fhit.hasSortData(hitGroup.getQuery().getRanking().getSorting());
+ } else {
+ return false;
+ }
+ }
+
+ public static Comparator<Hit> getComparator(Sorting sorting, Comparator<Hit> fallback) {
+ if (fallback == null) {
+ return (left, right) -> compareTwo(left, right, sorting);
+ } else {
+ return (left, right) -> compareWithFallback(left, right, sorting, fallback);
+ }
+ }
+
+ private static int compareTwo(Hit left, Hit right, Sorting sorting) {
+ if (left == null || right == null || !(left instanceof FastHit) || !(right instanceof FastHit)) {
+ return 0;
+ }
+ FastHit fl = (FastHit) left;
+ FastHit fr = (FastHit) right;
+ return FastHit.compareSortData(fl, fr, sorting);
+ }
+
+ private static int compareWithFallback(Hit left, Hit right, Sorting sorting, Comparator<Hit> fallback) {
+ if (left == null || right == null || !(left instanceof FastHit) || !(right instanceof FastHit)) {
+ return fallback.compare(left, right);
+ }
+ FastHit fl = (FastHit) left;
+ FastHit fr = (FastHit) right;
+ if (fl.hasSortData(sorting) && fr.hasSortData(sorting)) {
+ return FastHit.compareSortData(fl, fr, sorting);
+ } else {
+ return fallback.compare(left, right);
+ }
+ }
+}
diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java
index df72720a46c..f5e437c2410 100644
--- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java
+++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java
@@ -24,6 +24,7 @@ import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.cluster.PingableSearcher;
import com.yahoo.search.grouping.vespa.GroupingExecutor;
+import com.yahoo.search.query.Sorting;
import com.yahoo.search.result.Coverage;
import com.yahoo.search.result.ErrorHit;
import com.yahoo.search.result.ErrorMessage;
@@ -88,10 +89,9 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
* This is an endpoint - searchers will never propagate the search to any nested searcher.
*
* @param query the query to search
- * @param queryPacket the serialized query representation to pass to the search cluster
* @param execution the query execution context
*/
- protected abstract Result doSearch2(Query query, QueryPacket queryPacket, Execution execution);
+ protected abstract Result doSearch2(Query query, Execution execution);
protected abstract void doPartialFill(Result result, String summaryClass);
@@ -184,15 +184,10 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
if (root == null || root instanceof NullItem) // root can become null after resolving and transformation?
return new Result(query);
- QueryPacket queryPacket = createQueryPacket(serverId, query);
-
- if (isLoggingFine())
- getLogger().fine("made QueryPacket: " + queryPacket);
-
Result result = null;
if (result == null) {
- result = doSearch2(query, queryPacket, execution);
+ result = doSearch2(query, execution);
if (isLoggingFine())
getLogger().fine("Result NOT retrieved from cache");
@@ -209,6 +204,10 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
queryPacket.setCompressionLimit(compressionLimit);
if (compressionLimit != 0)
queryPacket.setCompressionType(query.properties().getString(PACKET_COMPRESSION_TYPE, "lz4"));
+
+ if (isLoggingFine())
+ getLogger().fine("made QueryPacket: " + queryPacket);
+
return queryPacket;
}
@@ -452,7 +451,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
return new FillHitsResult(skippedHits, lastError);
}
- private void extractDocumentInfo(FastHit hit, DocumentInfo document) {
+ private void extractDocumentInfo(FastHit hit, DocumentInfo document, Sorting sorting) {
hit.setSource(getName());
Number rank = document.getMetric();
@@ -462,6 +461,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
hit.setDistributionKey(document.getDistributionKey());
hit.setGlobalId(document.getGlobalId());
hit.setPartId(document.getPartId());
+ hit.setSortData(document.getSortData(), sorting);
}
protected DocsumDefinitionSet getDocsumDefinitionSet(Query query) {
@@ -498,6 +498,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
QueryPacketData queryPacketData,
Optional<Integer> channelDistributionKey) {
Query myQuery = result.getQuery();
+ Sorting sorting = myQuery.getRanking().getSorting();
for (DocumentInfo document : documents) {
@@ -510,7 +511,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
hit.setFillable();
hit.setCached(false);
- extractDocumentInfo(hit, document);
+ extractDocumentInfo(hit, document, sorting);
channelDistributionKey.ifPresent(hit::setDistributionKey);
result.hits().add(hit);