diff options
Diffstat (limited to 'container-search/src/main')
15 files changed, 179 insertions, 327 deletions
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 23ba3b0619c..3953190eac4 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 @@ -18,11 +18,9 @@ import com.yahoo.search.Query; import com.yahoo.search.Result; import com.yahoo.search.Searcher; import com.yahoo.search.config.ClusterConfig; -import com.yahoo.search.config.SchemaInfoConfig; import com.yahoo.search.dispatch.Dispatcher; import com.yahoo.search.query.ParameterParser; import com.yahoo.search.result.ErrorMessage; -import com.yahoo.search.schema.SchemaInfo; import com.yahoo.search.searchchain.Execution; import com.yahoo.vespa.streamingvisitors.VdsStreamingSearcher; import com.yahoo.yolean.Exceptions; @@ -78,7 +76,6 @@ public class ClusterSearcher extends Searcher { QrSearchersConfig qrsConfig, ClusterConfig clusterConfig, DocumentdbInfoConfig documentDbConfig, - SchemaInfo schemaInfo, ComponentRegistry<Dispatcher> dispatchers, VipStatus vipStatus, VespaDocumentAccess access) { @@ -102,11 +99,11 @@ public class ClusterSearcher extends Searcher { String uniqueServerId = UUID.randomUUID().toString(); if (searchClusterConfig.indexingmode() == STREAMING) { server = vdsCluster(uniqueServerId, searchClusterIndex, - searchClusterConfig, docSumParams, documentDbConfig, schemaInfo, access); + searchClusterConfig, docSumParams, documentDbConfig, access); vipStatus.addToRotation(server.getName()); } else { server = searchDispatch(searchClusterIndex, searchClusterName, uniqueServerId, - docSumParams, documentDbConfig, schemaInfo, dispatchers); + docSumParams, documentDbConfig, dispatchers); } } @@ -128,7 +125,6 @@ public class ClusterSearcher extends Searcher { String serverId, SummaryParameters docSumParams, DocumentdbInfoConfig documentdbInfoConfig, - SchemaInfo schemaInfo, ComponentRegistry<Dispatcher> dispatchers) { ClusterParams clusterParams = makeClusterParams(searchclusterIndex); ComponentId dispatcherComponentId = new ComponentId("dispatcher." + searchClusterName); @@ -136,7 +132,7 @@ public class ClusterSearcher extends Searcher { if (dispatcher == null) throw new IllegalArgumentException("Configuration error: No dispatcher " + dispatcherComponentId + " is configured"); - return new FastSearcher(serverId, dispatcher, docSumParams, clusterParams, documentdbInfoConfig, schemaInfo); + return new FastSearcher(serverId, dispatcher, docSumParams, clusterParams, documentdbInfoConfig); } private static VdsStreamingSearcher vdsCluster(String serverId, @@ -144,7 +140,6 @@ public class ClusterSearcher extends Searcher { QrSearchersConfig.Searchcluster searchClusterConfig, SummaryParameters docSumParams, DocumentdbInfoConfig documentdbInfoConfig, - SchemaInfo schemaInfo, VespaDocumentAccess access) { if (searchClusterConfig.searchdef().size() != 1) { throw new IllegalArgumentException("Search clusters in streaming search shall only contain a single searchdefinition : " + searchClusterConfig.searchdef()); @@ -154,7 +149,7 @@ public class ClusterSearcher extends Searcher { searcher.setSearchClusterName(searchClusterConfig.rankprofiles().configid()); searcher.setDocumentType(searchClusterConfig.searchdef(0)); searcher.setStorageClusterRouteSpec(searchClusterConfig.storagecluster().routespec()); - searcher.init(serverId, docSumParams, clusterParams, documentdbInfoConfig, schemaInfo); + searcher.init(serverId, docSumParams, clusterParams, documentdbInfoConfig); return searcher; } @@ -223,7 +218,7 @@ public class ClusterSearcher extends Searcher { } private Set<String> schemasHavingProfile(String profile, Execution.Context context) { - return context.schemaInfo().schemas().values().stream() + return context.schemaInfo().schemas().stream() .filter(schema -> schema.rankProfiles().containsKey(profile)) .map(schema -> schema.name()) .collect(Collectors.toSet()); @@ -239,8 +234,7 @@ public class ClusterSearcher extends Searcher { searcher.fill(result, summaryClass, execution); } else { if (result.hits().getErrorHit() == null) { - result.hits().addError(ErrorMessage.createTimeout("No time left to get summaries, query timeout was " + - query.getTimeout() + " ms")); + result.hits().addError(ErrorMessage.createTimeout("No time left to get summaries, query timeout was " + query.getTimeout() + " ms")); } } } else { diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinition.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinition.java index 33b912da42f..8a7d14d5f49 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinition.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinition.java @@ -1,11 +1,15 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.fastsearch; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.yahoo.data.access.Inspector; -import com.yahoo.search.schema.DocumentSummary; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.stream.Collectors; +import java.util.Set; /** * A docsum definition which knows how to decode a certain class of document @@ -17,26 +21,55 @@ import java.util.stream.Collectors; public class DocsumDefinition { private final String name; - private final Map<String, DocsumField> fields; + private final ImmutableList<DocsumField> fields; /** True if this contains dynamic fields */ private final boolean dynamic; - public DocsumDefinition(DocumentSummary documentSummary) { - this.name = documentSummary.name(); - this.dynamic = documentSummary.isDynamic(); - this.fields = documentSummary.fields() - .stream() - .map(field -> DocsumField.create(field.name(), field.type().asString())) - .collect(Collectors.toUnmodifiableMap(field -> field.getName(), - field -> field)); + // Mapping between field names and their index in this.fields + private final ImmutableMap<String, Integer> fieldNameToIndex; + + public DocsumDefinition(String name, List<DocsumField> fields) { + this.name = name; + this.dynamic = false; + this.fields = ImmutableList.copyOf(fields); + ImmutableMap.Builder<String, Integer> fieldNameToIndexBuilder = new ImmutableMap.Builder<>(); + int i = 0; + for (DocsumField field : fields) + fieldNameToIndexBuilder.put(field.name, i++); + this.fieldNameToIndex = fieldNameToIndexBuilder.build(); } - public String name() { return name; } - public Map<String, DocsumField> fields() { return fields; } + DocsumDefinition(DocumentdbInfoConfig.Documentdb.Summaryclass config) { + this.name = config.name(); - /** Returns whether this summary contains one or more dynamic fields */ - public boolean isDynamic() { return dynamic; } + List<DocsumField> fieldsBuilder = new ArrayList<>(); + Map<String, Integer> fieldNameToIndexBuilder = new HashMap<>(); + boolean dynamic = false; + for (DocumentdbInfoConfig.Documentdb.Summaryclass.Fields field : config.fields()) { + // no, don't switch the order of the two next lines :) + fieldNameToIndexBuilder.put(field.name(), fieldsBuilder.size()); + fieldsBuilder.add(DocsumField.create(field.name(), field.type())); + if (field.dynamic()) + dynamic = true; + } + this.dynamic = dynamic; + fields = ImmutableList.copyOf(fieldsBuilder); + fieldNameToIndex = ImmutableMap.copyOf(fieldNameToIndexBuilder); + } + + /** Returns the field at this index, or null if none */ + public DocsumField getField(int fieldIndex) { + if (fieldIndex >= fields.size()) return null; + return fields.get(fieldIndex); + } + + /** Returns the field with this name, or null if none */ + public DocsumField getField(String fieldName) { + Integer index = fieldNameToIndex.get(fieldName); + if (index == null) return null; + return getField(index); + } /** * Returns the given slime value as the type specified in this, or null if the type is not known. @@ -45,14 +78,35 @@ public class DocsumDefinition { * another has not. */ public Object convert(String fieldName, Inspector value) { - DocsumField field = fields.get(fieldName); - if (field == null || ! value.valid()) return null; - return field.convert(value); + DocsumField fieldType = getField(fieldName); + if (fieldType == null || ! value.valid()) return null; + return fieldType.convert(value); + } + + public Set<String> fieldNames() { + return fieldNameToIndex.keySet(); } @Override public String toString() { - return "docsum definition '" + name() + "'"; + return "docsum definition '" + getName() + "'"; + } + + public String getName() { + return name; + } + + public int getFieldCount() { + return fields.size(); + } + + public List<DocsumField> getFields() { + return fields; + } + + /** Returns whether this summary contains one or more dynamic fields */ + public boolean isDynamic() { + return dynamic; } } diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinitionSet.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinitionSet.java index 51da9965fea..1e0cfa3be9e 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinitionSet.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumDefinitionSet.java @@ -1,8 +1,7 @@ // Copyright Yahoo. 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.schema.DocumentSummary; -import com.yahoo.search.schema.Schema; +import com.google.common.collect.ImmutableMap; import com.yahoo.slime.BinaryFormat; import com.yahoo.data.access.Inspector; import com.yahoo.slime.Slime; @@ -11,8 +10,10 @@ import com.yahoo.prelude.ConfigurationException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import java.util.logging.Logger; import java.util.stream.Collectors; import static com.yahoo.data.access.Type.OBJECT; @@ -26,18 +27,16 @@ import static com.yahoo.data.access.Type.OBJECT; public final class DocsumDefinitionSet { public static final int SLIME_MAGIC_ID = 0x55555555; + private final static Logger log = Logger.getLogger(DocsumDefinitionSet.class.getName()); private final Map<String, DocsumDefinition> definitionsByName; - public DocsumDefinitionSet(Schema schema) { - this(schema.documentSummaries().values()); + public DocsumDefinitionSet(DocumentdbInfoConfig.Documentdb config) { + this(toDocsums(config)); } - public DocsumDefinitionSet(Collection<DocumentSummary> docsumDefinitions) { - this.definitionsByName = docsumDefinitions.stream() - .map(summary -> new DocsumDefinition(summary)) - .collect(Collectors.toUnmodifiableMap(summary -> summary.name(), - summary -> summary)); + public DocsumDefinitionSet(Collection<DocsumDefinition> docsumDefinitions) { + this.definitionsByName = ImmutableMap.copyOf(docsumDefinitions.stream().collect(Collectors.toMap(DocsumDefinition::getName, p -> p))); } /** @@ -46,22 +45,20 @@ public final class DocsumDefinitionSet { * @throws ConfigurationException if the requested summary class is not found and there is none called "default" */ public DocsumDefinition getDocsum(String summaryClass) { - if (summaryClass == null) - summaryClass = "default"; DocsumDefinition ds = definitionsByName.get(summaryClass); - if (ds == null) + if (ds == null) { ds = definitionsByName.get("default"); - if (ds == null) + } + if (ds == null) { throw new ConfigurationException("Fetched hit with summary class " + summaryClass + ", but this summary class is not in current summary config (" + this + ")" + " (that is, you asked for something unknown, and no default was found)"); + } return ds; } /** Do we have a summary definition with the given name */ public boolean hasDocsum(String summaryClass) { - if (summaryClass == null) - summaryClass = "default"; return definitionsByName.containsKey(summaryClass); } @@ -98,7 +95,7 @@ public final class DocsumDefinitionSet { if (sb.length() != 0) { sb.append(","); } - sb.append("[").append(e.getKey()).append(",").append(e.getValue().name()).append("]"); + sb.append("[").append(e.getKey()).append(",").append(e.getValue().getName()).append("]"); } return sb.toString(); } @@ -107,4 +104,13 @@ public final class DocsumDefinitionSet { return definitionsByName.size(); } + private static Collection<DocsumDefinition> toDocsums(DocumentdbInfoConfig.Documentdb config) { + Collection<DocsumDefinition> docsums = new ArrayList<>(); + for (int i = 0; i < config.summaryclass().size(); ++i) + docsums.add(new DocsumDefinition(config.summaryclass(i))); + if (docsums.isEmpty()) + log.warning("No summary classes found in DocumentdbInfoConfig.Documentdb"); + return docsums; + } + } diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumField.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumField.java index e6201a694cb..e412258ff15 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumField.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocsumField.java @@ -17,7 +17,7 @@ import java.util.logging.Logger; public abstract class DocsumField { private static final Logger log = Logger.getLogger(DocsumField.class.getName()); - private static final FieldFactory fieldFactory; + private static FieldFactory fieldFactory; private static class FieldFactory { @@ -32,7 +32,8 @@ public abstract class DocsumField { DocsumField create(String typename, String name) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return constructors.get(typename).newInstance(name); + DocsumField f = constructors.get(typename).newInstance(name); + return f; } } diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocumentDatabase.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocumentDatabase.java index 72ccf4aa1dd..67038e0e771 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocumentDatabase.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/DocumentDatabase.java @@ -2,8 +2,6 @@ package com.yahoo.prelude.fastsearch; import com.yahoo.search.schema.RankProfile; -import com.yahoo.search.schema.Schema; -import com.yahoo.search.schema.SchemaInfo; import com.yahoo.tensor.TensorType; import java.util.ArrayList; @@ -19,20 +17,48 @@ import java.util.stream.Collectors; */ public class DocumentDatabase { + // TODO: What about name conflicts when different search defs have the same rank profile/docsum? + public static final String MATCH_PROPERTY = "match"; public static final String SEARCH_DOC_TYPE_KEY = "documentdb.searchdoctype"; - private final Schema schema; + private final String name; private final DocsumDefinitionSet docsumDefSet; - public DocumentDatabase(Schema schema) { - this.schema = schema; - this.docsumDefSet = new DocsumDefinitionSet(schema); + private final Map<String, RankProfile> rankProfiles; + + public DocumentDatabase(DocumentdbInfoConfig.Documentdb documentDb) { + this(documentDb.name(), new DocsumDefinitionSet(documentDb), toRankProfiles(documentDb.rankprofile())); } - public Schema schema() { return schema; } + public DocumentDatabase(String name, DocsumDefinitionSet docsumDefinitionSet, Collection<RankProfile> rankProfiles) { + this.name = name; + this.docsumDefSet = docsumDefinitionSet; + this.rankProfiles = Map.copyOf(rankProfiles.stream().collect(Collectors.toMap(RankProfile::name, p -> p))); + } + + public String getName() { + return name; + } - /** Returns the document summary model in this which knows how to convert serialized data to hit fields. */ - public DocsumDefinitionSet getDocsumDefinitionSet() { return docsumDefSet; } + public DocsumDefinitionSet getDocsumDefinitionSet() { + return docsumDefSet; + } + + /** Returns an unmodifiable map of all the rank profiles in this indexed by rank profile name */ + public Map<String, RankProfile> rankProfiles() { return rankProfiles; } + + private static Collection<RankProfile> toRankProfiles(Collection<DocumentdbInfoConfig.Documentdb.Rankprofile> rankProfileConfigList) { + List<RankProfile> rankProfiles = new ArrayList<>(); + for (var profileConfig : rankProfileConfigList) { + var builder = new RankProfile.Builder(profileConfig.name()); + builder.setHasSummaryFeatures(profileConfig.hasSummaryFeatures()); + builder.setHasRankFeatures(profileConfig.hasRankFeatures()); + for (var inputConfig : profileConfig.input()) + builder.addInput(inputConfig.name(), TensorType.fromSpec(inputConfig.type())); + rankProfiles.add(builder.build()); + } + return rankProfiles; + } } 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 a094be943a2..094367dc140 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 @@ -183,7 +183,7 @@ public class FastHit extends Hit { /** For internal use */ public void addSummary(DocsumDefinition docsumDef, Inspector value) { if (removedFields != null) - removedFields.removeAll(docsumDef.fields().keySet()); + removedFields.removeAll(docsumDef.fieldNames()); if ( ! (summaries instanceof ArrayList) ) summaries = new ArrayList<>(8); summaries.add(0, new SummaryData(this, docsumDef, value, 1 + summaries.size())); } @@ -363,8 +363,8 @@ public class FastHit extends Hit { @Override public String toString() { - return super.toString() + " [fasthit, globalid: " + new GlobalId(globalId).toString() + ", partId: " + - partId + ", distributionkey: " + distributionKey + "]"; + return super.toString() + " [fasthit, globalid: " + new GlobalId(globalId).toString() + ", partId: " + + partId + ", distributionkey: " + distributionKey + "]"; } @Override @@ -562,7 +562,7 @@ public class FastHit extends Hit { void forEachFieldAsRaw(RawUtf8Consumer consumer) { data.traverse((ObjectTraverser)(name, value) -> { if (!shadowed(name) && !removed(name)) { - DocsumField fieldType = type.fields().get(name); + DocsumField fieldType = type.getField(name); if (fieldType != null) { if (fieldType.isString()) { byte[] utf8Value = value.asUtf8(); @@ -592,7 +592,7 @@ public class FastHit extends Hit { private boolean shadowed(String name) { if (hit.hasField(name)) return true; for (int i = 0; i < hit.summaries.size() - index; i++) { - if (hit.summaries.get(i).type.fields().containsKey(name)) + if (hit.summaries.get(i).type.fieldNames().contains(name)) return true; } return false; 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 33ad8d8c9a8..27a45753bb5 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 @@ -6,7 +6,6 @@ import com.yahoo.prelude.Pong; import com.yahoo.prelude.querytransform.QueryRewrite; import com.yahoo.search.Query; import com.yahoo.search.Result; -import com.yahoo.search.config.SchemaInfoConfig; import com.yahoo.search.dispatch.Dispatcher; import com.yahoo.search.dispatch.FillInvoker; import com.yahoo.search.dispatch.SearchInvoker; @@ -16,7 +15,6 @@ import com.yahoo.search.query.Ranking; import com.yahoo.search.result.ErrorMessage; import com.yahoo.search.result.Hit; import com.yahoo.search.result.HitGroup; -import com.yahoo.search.schema.SchemaInfo; import com.yahoo.search.searchchain.Execution; import java.io.IOException; @@ -53,13 +51,10 @@ public class FastSearcher extends VespaBackEndSearcher { * @param clusterParams the cluster number, and other cluster backend parameters * @param documentdbInfoConfig document database parameters */ - public FastSearcher(String serverId, - Dispatcher dispatcher, - SummaryParameters docSumParams, - ClusterParams clusterParams, - DocumentdbInfoConfig documentdbInfoConfig, - SchemaInfo schemaInfo) { - init(serverId, docSumParams, clusterParams, documentdbInfoConfig, schemaInfo); + public FastSearcher(String serverId, Dispatcher dispatcher, + SummaryParameters docSumParams, ClusterParams clusterParams, + DocumentdbInfoConfig documentdbInfoConfig) { + init(serverId, docSumParams, clusterParams, documentdbInfoConfig); this.dispatcher = dispatcher; } 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 21037be1a8b..3847e80d3c7 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 @@ -14,12 +14,10 @@ import com.yahoo.protect.Validator; import com.yahoo.search.Query; import com.yahoo.search.Result; import com.yahoo.search.cluster.PingableSearcher; -import com.yahoo.search.config.SchemaInfoConfig; import com.yahoo.search.schema.RankProfile; import com.yahoo.search.grouping.vespa.GroupingExecutor; import com.yahoo.search.result.ErrorMessage; import com.yahoo.search.result.Hit; -import com.yahoo.search.schema.SchemaInfo; import com.yahoo.search.searchchain.Execution; import com.yahoo.searchlib.aggregation.Grouping; @@ -109,7 +107,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { if (hasLocation(query.getModel().getQueryTree())) return true; // Needed to generate ranking features? - RankProfile rankProfile = documentDb.schema().rankProfiles().get(query.getRanking().getProfile()); + RankProfile rankProfile = documentDb.rankProfiles().get(query.getRanking().getProfile()); if (rankProfile == null) return true; // stay safe if (rankProfile.hasSummaryFeatures()) return true; if (query.getRanking().getListFeatures()) return true; @@ -135,12 +133,12 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { private void resolveDocumentDatabase(Query query) { DocumentDatabase docDb = getDocumentDatabase(query); if (docDb != null) { - query.getModel().setDocumentDb(docDb.schema().name()); + query.getModel().setDocumentDb(docDb.getName()); } } public final void init(String serverId, SummaryParameters docSumParams, ClusterParams clusterParams, - DocumentdbInfoConfig documentdbInfoConfig, SchemaInfo schemaInfo) { + DocumentdbInfoConfig documentdbInfoConfig) { this.serverId = serverId; this.name = clusterParams.searcherName; @@ -150,9 +148,10 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { if (documentdbInfoConfig != null) { for (DocumentdbInfoConfig.Documentdb docDb : documentdbInfoConfig.documentdb()) { - DocumentDatabase db = new DocumentDatabase(schemaInfo.schemas().get(docDb.name())); - if (documentDbs.isEmpty()) + DocumentDatabase db = new DocumentDatabase(docDb); + if (documentDbs.isEmpty()) { defaultDocumentDb = db; + } documentDbs.put(docDb.name(), db); } } @@ -160,7 +159,6 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { protected void transformQuery(Query query) { } - @Override public Result search(Query query, Execution execution) { // query root should not be null here Item root = query.getModel().getQueryTree().getRoot(); @@ -393,7 +391,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { private String decodeSummary(String summaryClass, FastHit hit, byte[] docsumdata) { DocumentDatabase db = getDocumentDatabase(hit.getQuery()); - hit.setField(Hit.SDDOCNAME_FIELD, db.schema().name()); + hit.setField(Hit.SDDOCNAME_FIELD, db.getName()); return decodeSummary(summaryClass, hit, docsumdata, db.getDocsumDefinitionSet()); } diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcProtobufFillInvoker.java b/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcProtobufFillInvoker.java index 57f7ea34a97..7a5ef94069d 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcProtobufFillInvoker.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcProtobufFillInvoker.java @@ -215,7 +215,7 @@ public class RpcProtobufFillInvoker extends FillInvoker { for (int i = 0; i < hits.size(); i++) { Inspector summary = summaries.entry(i).field("docsum"); if (summary.valid()) { - hits.get(i).setField(Hit.SDDOCNAME_FIELD, documentDb.schema().name()); + hits.get(i).setField(Hit.SDDOCNAME_FIELD, documentDb.getName()); hits.get(i).addSummary(documentDb.getDocsumDefinitionSet().getDocsum(summaryClass), summary); hits.get(i).setFilled(summaryClass); } else { diff --git a/container-search/src/main/java/com/yahoo/search/schema/DocumentSummary.java b/container-search/src/main/java/com/yahoo/search/schema/DocumentSummary.java deleted file mode 100644 index 12037ee6633..00000000000 --- a/container-search/src/main/java/com/yahoo/search/schema/DocumentSummary.java +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.search.schema; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * A document summary definition: Defines the schema on which a document hit may be - * represented in a Result. - * - * @author bratseth - */ -public class DocumentSummary { - - private final String name; - private final List<Field> fields; - private final boolean dynamic; - - private DocumentSummary(Builder builder) { - this.name = builder.name; - this.fields = List.copyOf(builder.fields); - this.dynamic = builder.dynamic; - } - - public String name() { return name; } - public List<Field> fields() { return fields; } - - /** Returns whether this contains fields which are generated dynamically from the query and field data. */ - public boolean isDynamic() { return dynamic; } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if ( ! (o instanceof DocumentSummary)) return false; - var other = (DocumentSummary)o; - if ( ! other.name.equals(this.name)) return false; - if ( other.dynamic != this.dynamic) return false; - if ( ! other.fields.equals(this.fields)) return false; - return true; - } - - @Override - public int hashCode() { - return Objects.hash(name, dynamic, fields); - } - - @Override - public String toString() { - return "document summary '" + name + "'"; - } - - public static class Builder { - - private final String name; - private final List<Field> fields = new ArrayList<>(); - private boolean dynamic; - - public Builder(String name) { - this.name = name; - } - - public Builder add(Field field) { - fields.add(field); - return this; - } - - public Builder setDynamic(boolean dynamic) { - this.dynamic = dynamic; - return this; - } - - public DocumentSummary build() { return new DocumentSummary(this); } - - } - - public static class Field { - - public enum Type { - bool, - byteType("byte"), - shortType("short"), - integer, - int64, - float16, - floatType("float"), - doubleType("double"), - string, - data, - raw, - longstring, - longdata, - jsonstring, - featuredata, - xmlstring, - tensor; - - private final String name; - - Type() { - this(null); - } - - Type(String name) { - this.name = name; - } - - /** Use this, not name() to retrieve the string value of this. */ - public String asString() { - return name != null ? name : name(); - } - - @Override - public String toString() { return asString(); } - - public static Type fromString(String name) { - return Arrays.stream(Type.values()).filter(t -> name.equals(t.asString())).findAny().orElseThrow(); - } - - } - - private final String name; - private final Type type; - - public Field(String name, String type) { - this(name, Type.fromString(type)); - } - - public Field(String name, Type type) { - this.name = name; - this.type = type; - } - - public String name() { return name; } - public Type type() { return type; } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if ( ! (o instanceof Field)) return false; - var other = (Field)o; - if ( ! other.name.equals(this.name)) return false; - if ( other.type != this.type) return false; - return true; - } - - @Override - public int hashCode() { - return Objects.hash(name, type); - } - - @Override - public String toString() { - return "summary field '" + name + "' " + type; - } - - } - -} diff --git a/container-search/src/main/java/com/yahoo/search/schema/RankProfile.java b/container-search/src/main/java/com/yahoo/search/schema/RankProfile.java index 39d4a389e6f..8267e5c937b 100644 --- a/container-search/src/main/java/com/yahoo/search/schema/RankProfile.java +++ b/container-search/src/main/java/com/yahoo/search/schema/RankProfile.java @@ -3,9 +3,7 @@ package com.yahoo.search.schema; import com.yahoo.tensor.TensorType; -import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -25,7 +23,7 @@ public class RankProfile { this.name = builder.name; this.hasSummaryFeatures = builder.hasSummaryFeatures; this.hasRankFeatures = builder.hasRankFeatures; - this.inputs = Collections.unmodifiableMap(builder.inputs); + this.inputs = Map.copyOf(builder.inputs); } public String name() { return name; } @@ -66,7 +64,7 @@ public class RankProfile { private final String name; private boolean hasSummaryFeatures = true; private boolean hasRankFeatures = true; - private final Map<String, TensorType> inputs = new LinkedHashMap<>(); + private final Map<String, TensorType> inputs = new HashMap<>(); public Builder(String name) { this.name = Objects.requireNonNull(name); diff --git a/container-search/src/main/java/com/yahoo/search/schema/Schema.java b/container-search/src/main/java/com/yahoo/search/schema/Schema.java index 2ab5a30fbd7..b66e6ce957a 100644 --- a/container-search/src/main/java/com/yahoo/search/schema/Schema.java +++ b/container-search/src/main/java/com/yahoo/search/schema/Schema.java @@ -3,9 +3,7 @@ package com.yahoo.search.schema; import com.yahoo.api.annotations.Beta; -import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -21,17 +19,14 @@ public class Schema { private final String name; private final Map<String, RankProfile> rankProfiles; - private final Map<String, DocumentSummary> documentSummaries; private Schema(Builder builder) { this.name = builder.name; - this.rankProfiles = Collections.unmodifiableMap(builder.rankProfiles); - this.documentSummaries = Collections.unmodifiableMap(builder.documentSummaries); + this.rankProfiles = Map.copyOf(builder.rankProfiles); } public String name() { return name; } public Map<String, RankProfile> rankProfiles() { return rankProfiles; } - public Map<String, DocumentSummary> documentSummaries() { return documentSummaries; } @Override public boolean equals(Object o) { @@ -40,13 +35,12 @@ public class Schema { Schema other = (Schema)o; if ( ! other.name.equals(this.name)) return false; if ( ! other.rankProfiles.equals(this.rankProfiles)) return false; - if ( ! other.documentSummaries.equals(this.documentSummaries)) return false; return true; } @Override public int hashCode() { - return Objects.hash(name, rankProfiles, documentSummaries); + return Objects.hash(name, rankProfiles); } @Override @@ -57,20 +51,14 @@ public class Schema { public static class Builder { private final String name; - private final Map<String, RankProfile> rankProfiles = new LinkedHashMap<>(); - private final Map<String, DocumentSummary> documentSummaries = new LinkedHashMap<>(); + private final Map<String, RankProfile> rankProfiles = new HashMap<>(); public Builder(String name) { this.name = Objects.requireNonNull(name); } public Builder add(RankProfile profile) { - rankProfiles.put(profile.name(), profile); - return this; - } - - public Builder add(DocumentSummary documentSummary) { - documentSummaries.put(documentSummary.name(), documentSummary); + rankProfiles.put(profile.name(), Objects.requireNonNull(profile)); return this; } 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 7bd66445512..4daf110fc54 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 @@ -2,17 +2,13 @@ package com.yahoo.search.schema; 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.Collection; -import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -43,12 +39,11 @@ public class SchemaInfo { private static final SchemaInfo empty = new SchemaInfo(List.of(), Map.of()); - private final Map<String, Schema> schemas; + private final List<Schema> schemas; /** The schemas contained in each content cluster indexed by cluster name */ private final Map<String, List<String>> clusters; - @Inject public SchemaInfo(IndexInfoConfig indexInfo, // will be used in the future SchemaInfoConfig schemaInfoConfig, QrSearchersConfig qrSearchersConfig) { @@ -56,14 +51,12 @@ public class SchemaInfo { } public SchemaInfo(List<Schema> schemas, Map<String, List<String>> clusters) { - Map<String, Schema> schemaMap = new LinkedHashMap<>(); - schemas.forEach(schema -> schemaMap.put(schema.name(), schema)); - this.schemas = Collections.unmodifiableMap(schemaMap); - this.clusters = Collections.unmodifiableMap(clusters); + this.schemas = List.copyOf(schemas); + this.clusters = Map.copyOf(clusters); } - /** Returns all schemas configured in this application, indexed by schema name. */ - public Map<String, Schema> schemas() { return schemas; } + /** Returns all schemas configured in this application. */ + public List<Schema> schemas() { return schemas; } public Session newSession(Query query) { return new Session(query.getModel().getSources(), query.getModel().getRestrict(), clusters, schemas); @@ -87,13 +80,13 @@ public class SchemaInfo { /** The schema information resolved to be relevant to this session. */ public static class Session { - private final Collection<Schema> schemas; + private final List<Schema> schemas; private Session(Set<String> sources, Set<String> restrict, Map<String, List<String>> clusters, - Map<String, Schema> candidates) { - this.schemas = resolveSchemas(sources, restrict, clusters, candidates.values()); + List<Schema> candidates) { + this.schemas = resolveSchemas(sources, restrict, clusters, candidates); } /** @@ -103,10 +96,10 @@ public class SchemaInfo { * * @return the possibly empty list of schemas matching the arguments */ - private static Collection<Schema> resolveSchemas(Set<String> sources, - Set<String> restrict, - Map<String, List<String>> clusters, - Collection<Schema> candidates) { + private static List<Schema> resolveSchemas(Set<String> sources, + Set<String> restrict, + Map<String, List<String>> clusters, + List<Schema> candidates) { if (sources.isEmpty()) return restrict.isEmpty() ? candidates : keep(restrict, candidates); @@ -121,7 +114,7 @@ public class SchemaInfo { return restrict.isEmpty() ? candidates : keep(restrict, candidates); } - private static List<Schema> keep(Set<String> names, Collection<Schema> schemas) { + private static List<Schema> keep(Set<String> names, List<Schema> schemas) { return schemas.stream().filter(schema -> names.contains(schema.name())).collect(Collectors.toList()); } 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 c5a74ece866..84ed9ae8e3d 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 @@ -1,17 +1,11 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.search.schema; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.yahoo.container.QrSearchersConfig; -import com.yahoo.prelude.fastsearch.DocsumDefinition; -import com.yahoo.prelude.fastsearch.DocsumField; -import com.yahoo.prelude.fastsearch.DocumentdbInfoConfig; import com.yahoo.search.config.SchemaInfoConfig; import com.yahoo.tensor.TensorType; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,7 +24,6 @@ class SchemaInfoConfigurer { static Schema toSchema(SchemaInfoConfig.Schema schemaInfoConfig) { Schema.Builder builder = new Schema.Builder(schemaInfoConfig.name()); - for (var profileConfig : schemaInfoConfig.rankprofile()) { RankProfile.Builder profileBuilder = new RankProfile.Builder(profileConfig.name()); profileBuilder.setHasSummaryFeatures(profileConfig.hasSummaryFeatures()); @@ -39,17 +32,6 @@ class SchemaInfoConfigurer { profileBuilder.addInput(inputConfig.name(), TensorType.fromSpec(inputConfig.type())); builder.add(profileBuilder.build()); } - - for (var summaryConfig : schemaInfoConfig.summaryclass()) { - DocumentSummary.Builder summaryBuilder = new DocumentSummary.Builder(summaryConfig.name()); - for (var field : summaryConfig.fields()) { - if (field.dynamic()) - summaryBuilder.setDynamic(true); - summaryBuilder.add(new DocumentSummary.Field(field.name(), field.type())); - } - builder.add(summaryBuilder.build()); - } - return builder.build(); } diff --git a/container-search/src/main/java/com/yahoo/search/searchchain/ExecutionFactory.java b/container-search/src/main/java/com/yahoo/search/searchchain/ExecutionFactory.java index bf8ef39001f..3e44b02618e 100644 --- a/container-search/src/main/java/com/yahoo/search/searchchain/ExecutionFactory.java +++ b/container-search/src/main/java/com/yahoo/search/searchchain/ExecutionFactory.java @@ -2,7 +2,6 @@ package com.yahoo.search.searchchain; import com.google.inject.Inject; -import com.yahoo.api.annotations.Beta; import com.yahoo.component.AbstractComponent; import com.yahoo.component.chain.Chain; import com.yahoo.component.chain.ChainsConfigurer; @@ -49,8 +48,6 @@ public class ExecutionFactory extends AbstractComponent { private final RendererRegistry rendererRegistry; private final Executor executor; - // TODO: Fix tests depending on HandlersConfigurerTestWrapper so that this constructor can be removed - @Beta @Inject public ExecutionFactory(ChainsConfig chainsConfig, IndexInfoConfig indexInfo, @@ -61,29 +58,9 @@ public class ExecutionFactory extends AbstractComponent { Linguistics linguistics, ComponentRegistry<Renderer> renderers, Executor executor) { - this(chainsConfig, - indexInfo, - new SchemaInfo(indexInfo, schemaInfo, clusters), - clusters, - searchers, - specialTokens, - linguistics, - renderers, - executor); - } - - public ExecutionFactory(ChainsConfig chainsConfig, - IndexInfoConfig indexInfo, - SchemaInfo schemaInfo, - QrSearchersConfig clusters, - ComponentRegistry<Searcher> searchers, - SpecialtokensConfig specialTokens, - Linguistics linguistics, - ComponentRegistry<Renderer> renderers, - Executor executor) { this.searchChainRegistry = createSearchChainRegistry(searchers, chainsConfig); this.indexFacts = new IndexFacts(new IndexModel(indexInfo, clusters)).freeze(); - this.schemaInfo = schemaInfo; + this.schemaInfo = new SchemaInfo(indexInfo, schemaInfo, clusters); this.specialTokens = new SpecialTokenRegistry(specialTokens); this.linguistics = linguistics; this.renderingExecutor = createRenderingExecutor(); @@ -101,7 +78,7 @@ public class ExecutionFactory extends AbstractComponent { Linguistics linguistics, ComponentRegistry<Renderer> renderers, Executor executor) { - this(chainsConfig, indexInfo, SchemaInfo.empty(), clusters, searchers, specialTokens, linguistics, renderers, executor); + this(chainsConfig, indexInfo, new SchemaInfoConfig.Builder().build(), clusters, searchers, specialTokens, linguistics, renderers, executor); } /** @deprecated pass the container threadpool */ @@ -113,7 +90,7 @@ public class ExecutionFactory extends AbstractComponent { SpecialtokensConfig specialTokens, Linguistics linguistics, ComponentRegistry<Renderer> renderers) { - this(chainsConfig, indexInfo, SchemaInfo.empty(), clusters, searchers, specialTokens, linguistics, renderers, null); + this(chainsConfig, indexInfo, new SchemaInfoConfig.Builder().build(), clusters, searchers, specialTokens, linguistics, renderers, null); } private SearchChainRegistry createSearchChainRegistry(ComponentRegistry<Searcher> searchers, @@ -167,7 +144,7 @@ public class ExecutionFactory extends AbstractComponent { public static ExecutionFactory empty() { return new ExecutionFactory(new ChainsConfig.Builder().build(), new IndexInfoConfig.Builder().build(), - SchemaInfo.empty(), + new SchemaInfoConfig.Builder().build(), new QrSearchersConfig.Builder().build(), new ComponentRegistry<>(), new SpecialtokensConfig.Builder().build(), |