summaryrefslogtreecommitdiffstats
path: root/container-search/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'container-search/src/main')
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/IndexFacts.java27
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java32
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java8
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java75
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java6
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/SourceRefResolver.java20
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/SourcesTarget.java1
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSearchChainException.java1
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSourceRefException.java1
-rw-r--r--container-search/src/main/java/com/yahoo/search/federation/sourceref/VirtualSourceResolver.java65
-rw-r--r--container-search/src/main/java/com/yahoo/search/querytransform/DefaultPositionSearcher.java4
-rw-r--r--container-search/src/main/java/com/yahoo/search/schema/SchemaInfo.java6
-rw-r--r--container-search/src/main/java/com/yahoo/search/schema/SchemaInfoConfigurer.java2
13 files changed, 146 insertions, 102 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java b/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java
index c0dce3734b2..e4e50f8f2ff 100644
--- a/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java
+++ b/container-search/src/main/java/com/yahoo/prelude/IndexFacts.java
@@ -3,9 +3,7 @@ package com.yahoo.prelude;
import com.yahoo.search.Query;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -29,8 +27,6 @@ import static com.yahoo.text.Lowercase.toLowerCase;
// TODO: Complete migration to SchemaInfo
public class IndexFacts {
- private final Map<String, List<String>> clusterByDocument;
-
private record DocumentTypeListOffset(int offset, SearchDefinition searchDefinition) { }
/** A Map of all known search definitions indexed by name */
@@ -56,7 +52,6 @@ public class IndexFacts {
public IndexFacts() {
searchDefinitions = Map.of();
clusters = Map.of();
- clusterByDocument = Map.of();
}
public IndexFacts(IndexModel indexModel) {
@@ -65,28 +60,6 @@ public class IndexFacts {
this.unionSearchDefinition = indexModel.getUnionSearchDefinition();
}
this.clusters = indexModel.getMasterClusters();
- clusterByDocument = invert(clusters);
- }
-
- private static Map<String, List<String>> invert(Map<String, List<String>> clusters) {
- Map<String, List<String>> result = new HashMap<>();
- for (Map.Entry<String,List<String>> entry : clusters.entrySet()) {
- for (String value : entry.getValue()) {
- addEntry(result, value, entry.getKey());
- }
- }
- return result;
- }
-
- private static void addEntry(Map<String, List<String>> result, String key, String value) {
- List<String> values = result.computeIfAbsent(key, k -> new ArrayList<>());
- values.add(value);
- }
-
- // Assumes that document names are equal to the search definition that contain them.
- public List<String> clustersHavingSearchDefinition(String searchDefinitionName) {
- List<String> clusters = clusterByDocument.get(searchDefinitionName);
- return clusters != null ? clusters : List.of();
}
private boolean notInitialized() {
diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
index 88cc7ad7b2d..b0456b941f4 100644
--- a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
+++ b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java
@@ -8,7 +8,6 @@ import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.container.QrSearchersConfig;
import com.yahoo.container.core.documentapi.VespaDocumentAccess;
import com.yahoo.container.handler.VipStatus;
-import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.fastsearch.ClusterParams;
import com.yahoo.prelude.fastsearch.DocumentdbInfoConfig;
import com.yahoo.prelude.fastsearch.FastSearcher;
@@ -22,6 +21,7 @@ import com.yahoo.search.dispatch.Dispatcher;
import com.yahoo.search.query.ParameterParser;
import com.yahoo.search.ranking.GlobalPhaseRanker;
import com.yahoo.search.result.ErrorMessage;
+import com.yahoo.search.schema.Cluster;
import com.yahoo.search.schema.SchemaInfo;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.vespa.streamingvisitors.StreamingSearcher;
@@ -29,7 +29,6 @@ import com.yahoo.yolean.Exceptions;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
@@ -39,6 +38,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RejectedExecutionException;
+import java.util.stream.Collectors;
import static com.yahoo.container.QrSearchersConfig.Searchcluster.Indexingmode.STREAMING;
@@ -59,6 +59,7 @@ public class ClusterSearcher extends Searcher {
// The set of document types contained in this search cluster
private final Set<String> schemas;
+ private final SchemaInfo schemaInfo;
private final long maxQueryTimeout; // in milliseconds
private final long maxQueryCacheTimeout; // in milliseconds
@@ -80,6 +81,7 @@ public class ClusterSearcher extends Searcher {
VespaDocumentAccess access) {
super(id);
this.executor = executor;
+ this.schemaInfo = schemaInfo;
int searchClusterIndex = clusterConfig.clusterId();
searchClusterName = clusterConfig.clusterName();
QrSearchersConfig.Searchcluster searchClusterConfig = getSearchClusterConfigFromClusterName(qrsConfig, searchClusterName);
@@ -156,19 +158,20 @@ public class ClusterSearcher extends Searcher {
}
/** Do not use, for internal testing purposes only. **/
- ClusterSearcher(Set<String> schemas, VespaBackEndSearcher searcher, Executor executor) {
- this.schemas = schemas;
+ ClusterSearcher(SchemaInfo schemaInfo, Set<String> schemas, VespaBackEndSearcher searcher, Executor executor) {
+ this.schemaInfo = schemaInfo;
searchClusterName = "testScenario";
maxQueryTimeout = DEFAULT_MAX_QUERY_TIMEOUT;
maxQueryCacheTimeout = DEFAULT_MAX_QUERY_CACHE_TIMEOUT;
server = searcher;
this.executor = executor;
this.globalPhaseRanker = null;
+ this.schemas = schemas;
}
/** Do not use, for internal testing purposes only. **/
- ClusterSearcher(Set<String> schemas) {
- this(schemas, null, null);
+ ClusterSearcher(SchemaInfo schemaInfo, Set<String> schemas) {
+ this(schemaInfo, schemas, null, null);
}
@Override
@@ -283,7 +286,7 @@ public class ClusterSearcher extends Searcher {
}
private Result searchMultipleDocumentTypes(Searcher searcher, Query query, Execution execution) {
- Set<String> schemas = resolveSchemas(query, execution.context().getIndexFacts());
+ Set<String> schemas = resolveSchemas(query);
List<Query> queries = createQueries(query, schemas);
if (queries.size() == 1) {
return perSchemaSearch(searcher, queries.get(0), execution);
@@ -316,13 +319,24 @@ public class ClusterSearcher extends Searcher {
}
}
- Set<String> resolveSchemas(Query query, IndexFacts indexFacts) {
+ private Set<String> resolveSourceSubset(Set<String> sources) {
+ Set<String> candidates = new HashSet<>();
+ for (String source : sources) {
+ Cluster cluster = schemaInfo.clusters().get(source);
+ if (cluster != null)
+ candidates.addAll(cluster.schemas());
+ }
+ return (candidates.isEmpty() ? sources : candidates).stream()
+ .filter(schemas::contains).collect(Collectors.toUnmodifiableSet());
+ }
+
+ Set<String> resolveSchemas(Query query) {
Set<String> restrict = query.getModel().getRestrict();
if (restrict == null || restrict.isEmpty()) {
Set<String> sources = query.getModel().getSources();
return (sources == null || sources.isEmpty())
? schemas
- : new HashSet<>(indexFacts.newSession(sources, Collections.emptyList(), schemas).documentTypes());
+ : resolveSourceSubset(sources);
} else {
return filterValidDocumentTypes(restrict);
}
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 5dab9d2988f..2e635d21f01 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
@@ -9,7 +9,6 @@ import com.yahoo.prelude.query.Item;
import com.yahoo.prelude.query.NullItem;
import com.yahoo.prelude.query.textualrepresentation.TextualQueryRepresentation;
import com.yahoo.prelude.querytransform.QueryRewrite;
-import com.yahoo.processing.request.CompoundName;
import com.yahoo.protect.Validator;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
@@ -223,7 +222,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
if (result.isFilled(summaryClass)) return; // TODO: Checked in the superclass - remove
List<Result> parts = partitionHits(result, summaryClass);
- if (parts.size() > 0) { // anything to fill at all?
+ if (!parts.isEmpty()) { // anything to fill at all?
for (Result r : parts) {
doPartialFill(r, summaryClass);
mergeErrorsInto(result, r);
@@ -379,11 +378,6 @@ public abstract class VespaBackEndSearcher extends PingableSearcher {
return new FillHitsResult(skippedHits, lastError);
}
- protected DocsumDefinitionSet getDocsumDefinitionSet(Query query) {
- DocumentDatabase db = getDocumentDatabase(query);
- return db.getDocsumDefinitionSet();
- }
-
private String decodeSummary(String summaryClass, FastHit hit, byte[] docsumdata) {
DocumentDatabase db = getDocumentDatabase(hit.getQuery());
hit.setField(Hit.SDDOCNAME_FIELD, db.schema().name());
diff --git a/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java b/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java
index e5393fe9b85..f40caac1562 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/FederationSearcher.java
@@ -11,7 +11,6 @@ import com.yahoo.component.chain.dependencies.Provides;
import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.errorhandling.Results;
import com.yahoo.errorhandling.Results.Builder;
-import com.yahoo.prelude.IndexFacts;
import com.yahoo.processing.IllegalInputException;
import com.yahoo.processing.request.CompoundName;
import com.yahoo.search.Query;
@@ -25,11 +24,14 @@ import com.yahoo.search.federation.sourceref.SingleTarget;
import com.yahoo.search.federation.sourceref.SourceRefResolver;
import com.yahoo.search.federation.sourceref.SourcesTarget;
import com.yahoo.search.federation.sourceref.UnresolvedSearchChainException;
+import com.yahoo.search.federation.sourceref.VirtualSourceResolver;
import com.yahoo.search.query.Properties;
import com.yahoo.search.result.ErrorMessage;
import com.yahoo.search.result.Hit;
import com.yahoo.search.result.HitGroup;
import com.yahoo.search.result.HitOrderer;
+import com.yahoo.search.schema.Cluster;
+import com.yahoo.search.schema.SchemaInfo;
import com.yahoo.search.searchchain.AsyncExecution;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.search.searchchain.ForkingSearcher;
@@ -41,6 +43,7 @@ import java.time.Clock;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -77,25 +80,34 @@ public class FederationSearcher extends ForkingSearcher {
private final SearchChainResolver searchChainResolver;
private final SourceRefResolver sourceRefResolver;
+ private final VirtualSourceResolver virtualSourceResolver;
private final TargetSelector<?> targetSelector;
private final Clock clock = Clock.systemUTC();
@Inject
- public FederationSearcher(FederationConfig config, ComponentRegistry<TargetSelector> targetSelectors) {
- this(createResolver(config), resolveSelector(config.targetSelector(), targetSelectors));
+ public FederationSearcher(FederationConfig config, SchemaInfo schemaInfo,
+ ComponentRegistry<TargetSelector> targetSelectors) {
+ this(createResolver(config),
+ VirtualSourceResolver.of(config),
+ resolveSelector(config.targetSelector(), targetSelectors),
+ createSchema2Clusters(schemaInfo));
}
// for testing
- public FederationSearcher(ComponentId id, SearchChainResolver searchChainResolver) {
- this(searchChainResolver, null);
+ public FederationSearcher(ComponentId id, SearchChainResolver searchChainResolver,
+ Map<String, List<String>> schema2Clusters) {
+ this(searchChainResolver, VirtualSourceResolver.of(), null, schema2Clusters);
}
private FederationSearcher(SearchChainResolver searchChainResolver,
- TargetSelector targetSelector) {
+ VirtualSourceResolver virtualSourceResolver,
+ TargetSelector targetSelector,
+ Map<String, List<String>> schema2Clusters) {
this.searchChainResolver = searchChainResolver;
- sourceRefResolver = new SourceRefResolver(searchChainResolver);
+ sourceRefResolver = new SourceRefResolver(searchChainResolver, schema2Clusters);
this.targetSelector = targetSelector;
+ this.virtualSourceResolver = virtualSourceResolver;
}
private static TargetSelector resolveSelector(String selectorId,
@@ -105,6 +117,16 @@ public class FederationSearcher extends ForkingSearcher {
"Missing target selector with id '" + selectorId + "'");
}
+ private static Map<String, List<String>> createSchema2Clusters(SchemaInfo schemaInfo) {
+ Map<String, List<String>> schema2Clusters = new HashMap<>();
+ for (Cluster cluster : schemaInfo.clusters().values()) {
+ for (String schema : cluster.schemas()) {
+ schema2Clusters.computeIfAbsent(schema, key -> new ArrayList<>()).add(cluster.name());
+ }
+ }
+ return schema2Clusters;
+ }
+
private static SearchChainResolver createResolver(FederationConfig config) {
SearchChainResolver.Builder builder = new SearchChainResolver.Builder();
@@ -160,7 +182,7 @@ public class FederationSearcher extends ForkingSearcher {
Result mergedResults = execution.search(query);
Results<SearchChainInvocationSpec, UnresolvedSearchChainException> targets =
- getTargets(query.getModel().getSources(), query.properties(), execution.context().getIndexFacts());
+ getTargets(query.getModel().getSources(), query.properties());
warnIfUnresolvedSearchChains(targets.errors(), mergedResults.hits());
Collection<SearchChainInvocationSpec> prunedTargets =
@@ -277,7 +299,7 @@ public class FederationSearcher extends ForkingSearcher {
return descriptions;
}
- private Set<String> getMessagesSet(List<UnresolvedSearchChainException> unresolvedSearchChainExceptions) {
+ private static Set<String> getMessagesSet(List<UnresolvedSearchChainException> unresolvedSearchChainExceptions) {
Set<String> messages = new LinkedHashSet<>();
for (UnresolvedSearchChainException exception : unresolvedSearchChainExceptions) {
messages.add(exception.getMessage());
@@ -370,9 +392,9 @@ public class FederationSearcher extends ForkingSearcher {
else { // fill timed out: Remove these hits as they are incomplete and may cause a race when accessed later
result.hits().addError(futureFilledResult.getSecond().createTimeoutError());
for (Iterator<Hit> i = futureFilledResult.getFirst().hits().unorderedDeepIterator(); i.hasNext(); ) {
- // Note that some of these hits may be filled, but as the fill thread may still be working on them
- // and we do not synchronize with it we need to discard all
- Hit removed = result.hits().remove(i.next().getId());
+ // Note that some of these hits may be filled, but as the fill thread may still be working on them,
+ // and we do not synchronize with it, we need to discard all.
+ result.hits().remove(i.next().getId());
}
}
}
@@ -421,18 +443,20 @@ public class FederationSearcher extends ForkingSearcher {
return orderer;
}
- private Results<SearchChainInvocationSpec, UnresolvedSearchChainException> getTargets(Set<String> sources, Properties properties, IndexFacts indexFacts) {
+ private Results<SearchChainInvocationSpec, UnresolvedSearchChainException> getTargets(Set<String> sources, Properties properties) {
return sources.isEmpty() ?
defaultSearchChains(properties):
- resolveSources(sources, properties, indexFacts);
+ resolveSources(sources, properties);
}
- private Results<SearchChainInvocationSpec, UnresolvedSearchChainException> resolveSources(Set<String> sources, Properties properties, IndexFacts indexFacts) {
+
+ private Results<SearchChainInvocationSpec, UnresolvedSearchChainException> resolveSources(Set<String> sourcesInQuery, Properties properties) {
Results.Builder<SearchChainInvocationSpec, UnresolvedSearchChainException> result = new Builder<>();
+ Set<String> sources = virtualSourceResolver.resolve(sourcesInQuery);
for (String source : sources) {
try {
- result.addAllData(sourceRefResolver.resolve(asSourceSpec(source), properties, indexFacts));
+ result.addAllData(sourceRefResolver.resolve(asSourceSpec(source), properties));
} catch (UnresolvedSearchChainException e) {
result.addError(e);
}
@@ -578,11 +602,7 @@ public class FederationSearcher extends ForkingSearcher {
/** Returns a result to fill for a query and chain, by creating it if necessary */
public Result get(Chain<Searcher> chain, Query query) {
- Map<Query,Result> resultsToFillForAChain = resultsToFill.get(chain);
- if (resultsToFillForAChain == null) {
- resultsToFillForAChain = new IdentityHashMap<>();
- resultsToFill.put(chain,resultsToFillForAChain);
- }
+ Map<Query, Result> resultsToFillForAChain = resultsToFill.computeIfAbsent(chain, k -> new IdentityHashMap<>());
Result resultsToFillForAChainAndQuery = resultsToFillForAChain.get(query);
if (resultsToFillForAChainAndQuery == null) {
@@ -686,27 +706,18 @@ public class FederationSearcher extends ForkingSearcher {
}
- private static class Window {
-
- private final int hits;
- private final int offset;
-
- public Window(int hits, int offset) {
- this.hits = hits;
- this.offset = offset;
- }
+ private record Window(int hits, int offset) {
public Integer get(CompoundName parameterName) {
if (parameterName.equals(Query.HITS)) return hits;
if (parameterName.equals(Query.OFFSET)) return offset;
return null;
}
-
+
public static Window from(Query query) {
return new Window(query.getHits(), query.getOffset());
}
-
public static Window from(Collection<Target> targets, Query query) {
if (targets.size() == 1) // preserve requested top-level offsets
return Window.from(query);
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java
index bfb5bf1a9ab..df91b968750 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SearchChainResolver.java
@@ -56,12 +56,8 @@ public class SearchChainResolver {
}
};
- public Builder addSearchChain(ComponentId searchChainId) {
- return addSearchChain(searchChainId, Collections.<String>emptyList());
- }
-
public Builder addSearchChain(ComponentId searchChainId, FederationOptions federationOptions) {
- return addSearchChain(searchChainId, federationOptions, Collections.<String>emptyList());
+ return addSearchChain(searchChainId, federationOptions, List.of());
}
public Builder addSearchChain(ComponentId searchChainId, List<String> documentTypes) {
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourceRefResolver.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourceRefResolver.java
index 7345868cae7..2e7849dd85a 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourceRefResolver.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourceRefResolver.java
@@ -2,11 +2,11 @@
package com.yahoo.search.federation.sourceref;
import com.yahoo.component.ComponentSpecification;
-import com.yahoo.prelude.IndexFacts;
import com.yahoo.processing.request.Properties;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -17,30 +17,30 @@ import java.util.Set;
public class SourceRefResolver {
private final SearchChainResolver searchChainResolver;
+ private final Map<String, List<String>> schema2Clusters;
- public SourceRefResolver(SearchChainResolver searchChainResolver) {
+ public SourceRefResolver(SearchChainResolver searchChainResolver, Map<String, List<String>> schema2Clusters) {
this.searchChainResolver = searchChainResolver;
+ this.schema2Clusters = schema2Clusters;
}
public Set<SearchChainInvocationSpec> resolve(ComponentSpecification sourceRef,
- Properties sourceToProviderMap,
- IndexFacts indexFacts) throws UnresolvedSearchChainException {
+ Properties sourceToProviderMap) throws UnresolvedSearchChainException {
try {
- return new LinkedHashSet<>(List.of(searchChainResolver.resolve(sourceRef, sourceToProviderMap)));
+ return Set.of(searchChainResolver.resolve(sourceRef, sourceToProviderMap));
} catch (UnresolvedSourceRefException e) {
- return resolveClustersWithDocument(sourceRef, sourceToProviderMap, indexFacts);
+ return resolveClustersWithDocument(sourceRef, sourceToProviderMap);
}
}
private Set<SearchChainInvocationSpec> resolveClustersWithDocument(ComponentSpecification sourceRef,
- Properties sourceToProviderMap,
- IndexFacts indexFacts)
+ Properties sourceToProviderMap)
throws UnresolvedSearchChainException {
if (hasOnlyName(sourceRef)) {
Set<SearchChainInvocationSpec> clusterSearchChains = new LinkedHashSet<>();
- List<String> clusters = indexFacts.clustersHavingSearchDefinition(sourceRef.getName());
+ List<String> clusters = schema2Clusters.getOrDefault(sourceRef.getName(), List.of());
for (String cluster : clusters) {
clusterSearchChains.add(resolveClusterSearchChain(cluster, sourceRef, sourceToProviderMap));
}
@@ -48,9 +48,7 @@ public class SourceRefResolver {
if ( ! clusterSearchChains.isEmpty())
return clusterSearchChains;
}
-
throw UnresolvedSourceRefException.createForMissingSourceRef(sourceRef);
-
}
private SearchChainInvocationSpec resolveClusterSearchChain(String cluster,
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourcesTarget.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourcesTarget.java
index 54b022e0b97..b6d99758c7b 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourcesTarget.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/SourcesTarget.java
@@ -1,7 +1,6 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.federation.sourceref;
-
import com.google.common.base.Joiner;
import com.yahoo.component.ComponentId;
import com.yahoo.component.ComponentSpecification;
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSearchChainException.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSearchChainException.java
index 3cf2776259c..0c8562e6032 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSearchChainException.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSearchChainException.java
@@ -5,7 +5,6 @@ package com.yahoo.search.federation.sourceref;
* Thrown if a search chain can not be resolved from one or more ids.
* @author Tony Vaagenes
*/
-@SuppressWarnings("serial")
public class UnresolvedSearchChainException extends Exception {
public UnresolvedSearchChainException(String msg) {
super(msg);
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSourceRefException.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSourceRefException.java
index a7da7a7ee04..fa2c1da13f0 100644
--- a/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSourceRefException.java
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/UnresolvedSourceRefException.java
@@ -6,7 +6,6 @@ import com.yahoo.component.ComponentSpecification;
/**
* @author Tony Vaagenes
*/
-@SuppressWarnings("serial")
class UnresolvedSourceRefException extends UnresolvedSearchChainException {
UnresolvedSourceRefException(String msg) {
super(msg);
diff --git a/container-search/src/main/java/com/yahoo/search/federation/sourceref/VirtualSourceResolver.java b/container-search/src/main/java/com/yahoo/search/federation/sourceref/VirtualSourceResolver.java
new file mode 100644
index 00000000000..fc07d12d429
--- /dev/null
+++ b/container-search/src/main/java/com/yahoo/search/federation/sourceref/VirtualSourceResolver.java
@@ -0,0 +1,65 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.search.federation.sourceref;
+
+import com.yahoo.search.federation.FederationConfig;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Multiple sources like contentcluster.schema1, contencluster.schema2 needs to respond
+ * when source is the prefix contentcluster. This is done by generating map from virtual source
+ * to the fully qualified ones, and resolving from there.
+ *
+ * @author baldersheim
+ */
+public class VirtualSourceResolver {
+ private final Map<String, Set<String>> virtualSources;
+ private VirtualSourceResolver(Map<String, Set<String>> virtualSources) {
+ this.virtualSources = virtualSources;
+ }
+ public static VirtualSourceResolver of() {
+ return new VirtualSourceResolver(Map.of());
+ }
+ public static VirtualSourceResolver of(Set<String> targets) {
+ return new VirtualSourceResolver(createVirtualSources(targets));
+ }
+ private static Map<String, Set<String>> createVirtualSources(Set<String> targets) {
+ Set<String> virtualSources = targets.stream()
+ .filter(id -> id.contains("."))
+ .map(id -> id.substring(0, id.indexOf('.')))
+ .collect(Collectors.toUnmodifiableSet());
+ if (virtualSources.isEmpty()) return Map.of();
+ Map<String, Set<String>> virtualSourceMap = new HashMap<>();
+ for (String virtualSource : virtualSources) {
+ String prefix = virtualSource + ".";
+ Set<String> sources = targets.stream()
+ .filter(id -> id.startsWith(prefix))
+ .collect(Collectors.toUnmodifiableSet());
+ virtualSourceMap.put(virtualSource, sources);
+ }
+ return virtualSourceMap;
+ }
+ public static VirtualSourceResolver of(FederationConfig config) {
+ return of(config.target().stream().map(FederationConfig.Target::id).collect(Collectors.toUnmodifiableSet()));
+ }
+ public Set<String> resolve(Set<String> sourcesInQuery) {
+ boolean hasMapping = sourcesInQuery.stream().anyMatch(virtualSources::containsKey);
+ if (hasMapping) {
+ Set<String> resolved = new HashSet<>();
+ for (String source : sourcesInQuery) {
+ var subSources = virtualSources.get(source);
+ if (subSources != null) {
+ resolved.addAll(subSources);
+ } else {
+ resolved.add(source);
+ }
+ }
+ return resolved;
+ }
+ return sourcesInQuery;
+ }
+}
diff --git a/container-search/src/main/java/com/yahoo/search/querytransform/DefaultPositionSearcher.java b/container-search/src/main/java/com/yahoo/search/querytransform/DefaultPositionSearcher.java
index 86684603a45..4cb19bff740 100644
--- a/container-search/src/main/java/com/yahoo/search/querytransform/DefaultPositionSearcher.java
+++ b/container-search/src/main/java/com/yahoo/search/querytransform/DefaultPositionSearcher.java
@@ -33,10 +33,6 @@ public class DefaultPositionSearcher extends Searcher {
this.useV8GeoPositions = cfg.usev8geopositions();
}
- DefaultPositionSearcher() {
- this.useV8GeoPositions = false;
- }
-
@Override
public com.yahoo.search.Result search(Query query, Execution execution) {
Location location = query.getRanking().getLocation();
diff --git a/container-search/src/main/java/com/yahoo/search/schema/SchemaInfo.java b/container-search/src/main/java/com/yahoo/search/schema/SchemaInfo.java
index bbd303039cf..263fa4058c7 100644
--- a/container-search/src/main/java/com/yahoo/search/schema/SchemaInfo.java
+++ b/container-search/src/main/java/com/yahoo/search/schema/SchemaInfo.java
@@ -5,11 +5,9 @@ import com.yahoo.api.annotations.Beta;
import com.yahoo.component.annotation.Inject;
import com.yahoo.container.QrSearchersConfig;
import com.yahoo.search.Query;
-import com.yahoo.search.config.IndexInfoConfig;
import com.yahoo.search.config.SchemaInfoConfig;
import com.yahoo.tensor.TensorType;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -65,7 +63,7 @@ public class SchemaInfo {
/** Returns all schemas configured in this application, indexed by schema name. */
public Map<String, Schema> schemas() { return schemas; }
- /** Returns information about all clusters available for searching in this applications, indexed by cluyster name. */
+ /** Returns information about all clusters available for searching in this application, indexed by cluster name. */
public Map<String, Cluster> clusters() { return clusters; }
public Session newSession(Query query) {
@@ -103,6 +101,8 @@ public class SchemaInfo {
/** Returns true if this only searches streaming clusters. */
public boolean isStreaming() { return isStreaming; }
+ public Collection<Schema> schemas() { return schemas; }
+
/**
* Looks up a field or field set by the given name or alias
* in the schemas resolved for this query.
diff --git a/container-search/src/main/java/com/yahoo/search/schema/SchemaInfoConfigurer.java b/container-search/src/main/java/com/yahoo/search/schema/SchemaInfoConfigurer.java
index 84cf1744e27..b70f5145e56 100644
--- a/container-search/src/main/java/com/yahoo/search/schema/SchemaInfoConfigurer.java
+++ b/container-search/src/main/java/com/yahoo/search/schema/SchemaInfoConfigurer.java
@@ -16,7 +16,7 @@ import java.util.List;
class SchemaInfoConfigurer {
static List<Schema> toSchemas(SchemaInfoConfig schemaInfoConfig) {
- return schemaInfoConfig.schema().stream().map(config -> toSchema(config)).toList();
+ return schemaInfoConfig.schema().stream().map(SchemaInfoConfigurer::toSchema).toList();
}
static Schema toSchema(SchemaInfoConfig.Schema schemaInfoConfig) {