diff options
author | Jon Bratseth <bratseth@gmail.com> | 2022-05-19 12:03:06 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2022-05-19 12:03:06 +0200 |
commit | 5c24dc5c9642a8d9ed70aee4c950fd0678a1ebec (patch) | |
tree | bd9b74bf00c832456f0b83c1b2cd7010be387d68 /config-model/src/main/java/com/yahoo/schema/processing/IndexingOutputs.java | |
parent | f17c4fe7de4c55f5c4ee61897eab8c2f588d8405 (diff) |
Rename the 'searchdefinition' package to 'schema'
Diffstat (limited to 'config-model/src/main/java/com/yahoo/schema/processing/IndexingOutputs.java')
-rw-r--r-- | config-model/src/main/java/com/yahoo/schema/processing/IndexingOutputs.java | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/config-model/src/main/java/com/yahoo/schema/processing/IndexingOutputs.java b/config-model/src/main/java/com/yahoo/schema/processing/IndexingOutputs.java new file mode 100644 index 00000000000..ea65a223686 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/schema/processing/IndexingOutputs.java @@ -0,0 +1,144 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.schema.processing; + +import com.yahoo.config.application.api.DeployLogger; +import com.yahoo.schema.RankProfileRegistry; +import com.yahoo.document.DataType; +import com.yahoo.document.Field; +import com.yahoo.schema.Schema; +import com.yahoo.schema.document.SDField; +import com.yahoo.vespa.documentmodel.SummaryField; +import com.yahoo.vespa.documentmodel.SummaryTransform; +import com.yahoo.vespa.indexinglanguage.ExpressionConverter; +import com.yahoo.vespa.indexinglanguage.expressions.*; +import com.yahoo.vespa.model.container.search.QueryProfiles; + +import java.util.*; + +/** + * This processor modifies all indexing scripts so that they output to the owning field by default. It also prevents + * any output expression from writing to any field except for the owning field. Finally, for <code>SummaryExpression</code>, + * this processor expands to write all appropriate summary fields. + * + * @author Simon Thoresen Hult + */ +public class IndexingOutputs extends Processor { + + public IndexingOutputs(Schema schema, DeployLogger deployLogger, RankProfileRegistry rankProfileRegistry, QueryProfiles queryProfiles) { + super(schema, deployLogger, rankProfileRegistry, queryProfiles); + } + + @Override + public void process(boolean validate, boolean documentsOnly) { + for (SDField field : schema.allConcreteFields()) { + ScriptExpression script = field.getIndexingScript(); + if (script == null) continue; + + Set<String> summaryFields = new TreeSet<>(); + findSummaryTo(schema, field, summaryFields, summaryFields); + MyConverter converter = new MyConverter(schema, field, summaryFields, validate); + field.setIndexingScript((ScriptExpression)converter.convert(script)); + } + } + + public void findSummaryTo(Schema schema, SDField field, Set<String> dynamicSummary, Set<String> staticSummary) { + var summaryFields = schema.getSummaryFields(field); + if (summaryFields.isEmpty()) { + fillSummaryToFromField(field, dynamicSummary, staticSummary); + } else { + fillSummaryToFromSearch(schema, field, summaryFields, dynamicSummary, staticSummary); + } + } + + private void fillSummaryToFromSearch(Schema schema, SDField field, List<SummaryField> summaryFields, + Set<String> dynamicSummary, Set<String> staticSummary) { + for (SummaryField summaryField : summaryFields) { + fillSummaryToFromSummaryField(schema, field, summaryField, dynamicSummary, staticSummary); + } + } + + private void fillSummaryToFromSummaryField(Schema schema, SDField field, SummaryField summaryField, + Set<String> dynamicSummary, Set<String> staticSummary) { + SummaryTransform summaryTransform = summaryField.getTransform(); + String summaryName = summaryField.getName(); + if (summaryTransform.isDynamic() && summaryField.getSourceCount() > 2) { + // Avoid writing to summary fields that have more than a single input field, as that is handled by the + // summary rewriter in the search core. + return; + } + if (summaryTransform.isDynamic()) { + DataType fieldType = field.getDataType(); + if (fieldType != DataType.URI && fieldType != DataType.STRING) { + warn(schema, field, "Dynamic summaries are only supported for fields of type " + + "string, ignoring summary field '" + summaryField.getName() + + "' for sd field '" + field.getName() + "' of type " + + fieldType.getName() + "."); + return; + } + dynamicSummary.add(summaryName); + } else if (summaryTransform != SummaryTransform.ATTRIBUTE) { + staticSummary.add(summaryName); + } + } + + private static void fillSummaryToFromField(SDField field, Set<String> dynamicSummary, Set<String> staticSummary) { + for (SummaryField summaryField : field.getSummaryFields().values()) { + String summaryName = summaryField.getName(); + if (summaryField.getTransform().isDynamic()) { + dynamicSummary.add(summaryName); + } else { + staticSummary.add(summaryName); + } + } + } + + private class MyConverter extends ExpressionConverter { + + final Schema schema; + final Field field; + final Set<String> summaryFields; + final boolean validate; + + MyConverter(Schema schema, Field field, Set<String> summaryFields, boolean validate) { + this.schema = schema; + this.field = field; + this.summaryFields = summaryFields.isEmpty() ? Collections.singleton(field.getName()) : summaryFields; + this.validate = validate; + } + + @Override + protected boolean shouldConvert(Expression exp) { + if ( ! (exp instanceof OutputExpression)) { + return false; + } + String fieldName = ((OutputExpression)exp).getFieldName(); + if (fieldName == null) { + return true; // inject appropriate field name + } + if ( validate && ! fieldName.equals(field.getName())) { + fail(schema, field, "Indexing expression '" + exp + "' attempts to write to a field other than '" + + field.getName() + "'."); + } + return false; + } + + @Override + protected Expression doConvert(Expression exp) { + List<Expression> ret = new LinkedList<>(); + if (exp instanceof AttributeExpression) { + ret.add(new AttributeExpression(field.getName())); + } else if (exp instanceof IndexExpression) { + ret.add(new IndexExpression(field.getName())); + } else if (exp instanceof SummaryExpression) { + for (String fieldName : summaryFields) { + ret.add(new SummaryExpression(fieldName)); + } + } else { + throw new UnsupportedOperationException(exp.getClass().getName()); + } + return new StatementExpression(ret); + } + + } + +} |