diff options
Diffstat (limited to 'container-search/src/main/java/com/yahoo/prelude/fastsearch')
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); |