aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/schema/processing/AdjustPositionSummaryFields.java
diff options
context:
space:
mode:
Diffstat (limited to 'config-model/src/main/java/com/yahoo/schema/processing/AdjustPositionSummaryFields.java')
-rw-r--r--config-model/src/main/java/com/yahoo/schema/processing/AdjustPositionSummaryFields.java135
1 files changed, 135 insertions, 0 deletions
diff --git a/config-model/src/main/java/com/yahoo/schema/processing/AdjustPositionSummaryFields.java b/config-model/src/main/java/com/yahoo/schema/processing/AdjustPositionSummaryFields.java
new file mode 100644
index 00000000000..6c2d62f37cb
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/schema/processing/AdjustPositionSummaryFields.java
@@ -0,0 +1,135 @@
+// 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.config.model.api.ModelContext;
+import com.yahoo.document.ArrayDataType;
+import com.yahoo.document.DataType;
+import com.yahoo.document.PositionDataType;
+import com.yahoo.schema.RankProfileRegistry;
+import com.yahoo.schema.Schema;
+import com.yahoo.schema.document.Attribute;
+import com.yahoo.schema.document.GeoPos;
+import com.yahoo.schema.document.ImmutableSDField;
+import com.yahoo.vespa.documentmodel.DocumentSummary;
+import com.yahoo.vespa.documentmodel.SummaryField;
+import com.yahoo.vespa.documentmodel.SummaryField.Source;
+import com.yahoo.vespa.documentmodel.SummaryTransform;
+import com.yahoo.vespa.model.container.search.QueryProfiles;
+
+/*
+ * Adjusts position summary fields by adding derived summary fields (.distance and .position) and setting summary
+ * transform and source.
+ */
+public class AdjustPositionSummaryFields extends Processor {
+
+ public AdjustPositionSummaryFields(Schema schema, DeployLogger deployLogger, RankProfileRegistry rankProfileRegistry, QueryProfiles queryProfiles) {
+ super(schema, deployLogger, rankProfileRegistry, queryProfiles);
+ }
+
+ private boolean useV8GeoPositions = false;
+
+ @Override
+ public void process(boolean validate, boolean documentsOnly, ModelContext.Properties properties) {
+ this.useV8GeoPositions = properties.featureFlags().useV8GeoPositions();
+ process(validate, documentsOnly);
+ }
+
+ @Override
+ public void process(boolean validate, boolean documentsOnly) {
+ for (DocumentSummary summary : schema.getSummaries().values()) {
+ scanSummary(summary);
+ }
+ }
+
+ private void scanSummary(DocumentSummary summary) {
+ for (SummaryField summaryField : summary.getSummaryFields().values()) {
+ if ( ! GeoPos.isAnyPos(summaryField.getDataType())) continue;
+
+ String originalSource = summaryField.getSingleSource();
+ if (originalSource.indexOf('.') == -1) { // Eliminate summary fields with pos.x or pos.y as source
+ ImmutableSDField sourceField = schema.getField(originalSource);
+ if (sourceField != null) {
+ String zCurve = null;
+ if (sourceField.getDataType().equals(summaryField.getDataType())) {
+ zCurve = PositionDataType.getZCurveFieldName(originalSource);
+ } else if (sourceField.getDataType().equals(makeZCurveDataType(summaryField.getDataType())) &&
+ hasZCurveSuffix(originalSource)) {
+ zCurve = originalSource;
+ }
+ if (zCurve != null) {
+ if (hasPositionAttribute(zCurve)) {
+ Source source = new Source(zCurve);
+ adjustPositionField(summary, summaryField, source);
+ } else if (sourceField.isImportedField() || !summaryField.getName().equals(originalSource)) {
+ fail(summaryField, "No position attribute '" + zCurve + "'");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void adjustPositionField(DocumentSummary summary, SummaryField summaryField, Source source) {
+ summaryField.setTransform(SummaryTransform.GEOPOS);
+ summaryField.getSources().clear();
+ summaryField.addSource(source);
+ ensureSummaryField(summary,
+ PositionDataType.getPositionSummaryFieldName(summaryField.getName()),
+ DataType.getArray(DataType.STRING),
+ source,
+ SummaryTransform.POSITIONS);
+ ensureSummaryField(summary,
+ PositionDataType.getDistanceSummaryFieldName(summaryField.getName()),
+ DataType.INT,
+ source,
+ SummaryTransform.DISTANCE);
+ }
+
+ private void ensureSummaryField(DocumentSummary summary, String fieldName, DataType dataType, Source source, SummaryTransform transform) {
+ SummaryField oldField = schema.getSummaryField(fieldName);
+ if (oldField == null) {
+ if (useV8GeoPositions) return;
+ SummaryField newField = new SummaryField(fieldName, dataType, transform);
+ newField.addSource(source);
+ summary.add(newField);
+ return;
+ }
+ if (!oldField.getDataType().equals(dataType)) {
+ fail(oldField, "exists with type '" + oldField.getDataType().toString() + "', should be of type '" + dataType.toString() + "'");
+ }
+ if (oldField.getTransform() != transform) {
+ fail(oldField, "has summary transform '" + oldField.getTransform().toString() + "', should have transform '" + transform.toString() + "'");
+ }
+ if (oldField.getSourceCount() != 1 || !oldField.getSingleSource().equals(source.getName())) {
+ fail(oldField, "has source '" + oldField.getSources().toString() + "', should have source '" + source + "'");
+ }
+ if (useV8GeoPositions) return;
+ summary.add(oldField);
+ }
+
+ private boolean hasPositionAttribute(String name) {
+ Attribute attribute = schema.getAttribute(name);
+ if (attribute == null) {
+ ImmutableSDField field = schema.getField(name);
+ if (field != null && field.isImportedField()) {
+ attribute = field.getAttribute();
+ }
+ }
+ return attribute != null && attribute.isPosition();
+ }
+
+ private static boolean hasZCurveSuffix(String name) {
+ String suffix = PositionDataType.getZCurveFieldName("");
+ return name.length() > suffix.length() && name.substring(name.length() - suffix.length()).equals(suffix);
+ }
+
+ private static DataType makeZCurveDataType(DataType dataType) {
+ return dataType instanceof ArrayDataType ? DataType.getArray(DataType.LONG) : DataType.LONG;
+ }
+
+ private void fail(SummaryField summaryField, String msg) {
+ throw newProcessException(schema.getName(), summaryField.getName(), msg);
+ }
+
+}