summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--container-search/abi-spec.json18
-rw-r--r--container-search/src/main/java/com/yahoo/search/Query.java2
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/Model.java14
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/Ranking.java105
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/profile/types/FieldDescription.java2
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java20
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java44
-rw-r--r--container-search/src/test/java/com/yahoo/search/query/test/RankFeaturesTestCase.java8
8 files changed, 144 insertions, 69 deletions
diff --git a/container-search/abi-spec.json b/container-search/abi-spec.json
index 94baaf4ef52..b1b80eac3a4 100644
--- a/container-search/abi-spec.json
+++ b/container-search/abi-spec.json
@@ -5224,7 +5224,7 @@
"public void setType(java.lang.String)",
"public boolean equals(java.lang.Object)",
"public int hashCode()",
- "public java.lang.Object clone()",
+ "public com.yahoo.search.query.Model clone()",
"public com.yahoo.search.query.Model cloneFor(com.yahoo.search.Query)",
"public com.yahoo.search.Query getParent()",
"public void setParent(com.yahoo.search.Query)",
@@ -5238,7 +5238,8 @@
"public com.yahoo.search.searchchain.Execution getExecution()",
"public static com.yahoo.search.query.Model getFrom(com.yahoo.search.Query)",
"public java.lang.String toString()",
- "public void prepare(com.yahoo.search.query.Ranking)"
+ "public void prepare(com.yahoo.search.query.Ranking)",
+ "public bridge synthetic java.lang.Object clone()"
],
"fields": [
"public static final java.lang.String MODEL",
@@ -5390,14 +5391,17 @@
"public com.yahoo.search.query.ranking.MatchPhase getMatchPhase()",
"public com.yahoo.search.query.ranking.Matching getMatching()",
"public com.yahoo.search.query.ranking.SoftTimeout getSoftTimeout()",
- "public java.lang.Object clone()",
- "public boolean equals(java.lang.Object)",
- "public int hashCode()",
"public com.yahoo.search.query.Sorting getSorting()",
"public void setSorting(com.yahoo.search.query.Sorting)",
"public void setSorting(java.lang.String)",
"public static com.yahoo.search.query.Ranking getFrom(com.yahoo.search.Query)",
- "public void prepare()"
+ "public void prepare()",
+ "public com.yahoo.search.Query getParent()",
+ "public com.yahoo.search.query.Ranking clone()",
+ "public com.yahoo.search.query.Ranking cloneFor(com.yahoo.search.Query)",
+ "public boolean equals(java.lang.Object)",
+ "public int hashCode()",
+ "public bridge synthetic java.lang.Object clone()"
],
"fields": [
"public static final com.yahoo.processing.request.CompoundName RANKFEATURES",
@@ -6853,6 +6857,7 @@
],
"methods": [
"public void <init>()",
+ "public void <init>(com.yahoo.search.query.Ranking)",
"public void put(java.lang.String, double)",
"public void put(java.lang.String, com.yahoo.tensor.Tensor)",
"public void put(java.lang.String, java.lang.String)",
@@ -6867,6 +6872,7 @@
"public boolean equals(java.lang.Object)",
"public int hashCode()",
"public com.yahoo.search.query.ranking.RankFeatures clone()",
+ "public com.yahoo.search.query.ranking.RankFeatures cloneFor(com.yahoo.search.query.Ranking)",
"public java.lang.String toString()",
"public bridge synthetic java.lang.Object clone()"
],
diff --git a/container-search/src/main/java/com/yahoo/search/Query.java b/container-search/src/main/java/com/yahoo/search/Query.java
index fbbe665db7f..9d2c7f6eec9 100644
--- a/container-search/src/main/java/com/yahoo/search/Query.java
+++ b/container-search/src/main/java/com/yahoo/search/Query.java
@@ -995,7 +995,7 @@ public class Query extends com.yahoo.processing.Request implements Cloneable {
private void copyPropertiesTo(Query clone) {
clone.model = model.cloneFor(clone);
clone.select = select.cloneFor(clone);
- clone.ranking = (Ranking) ranking.clone();
+ clone.ranking = ranking.cloneFor(clone);
clone.presentation = (Presentation) presentation.clone();
clone.context = getContext(true).cloneFor(clone);
diff --git a/container-search/src/main/java/com/yahoo/search/query/Model.java b/container-search/src/main/java/com/yahoo/search/query/Model.java
index 81efadbba0a..0cc7a50141f 100644
--- a/container-search/src/main/java/com/yahoo/search/query/Model.java
+++ b/container-search/src/main/java/com/yahoo/search/query/Model.java
@@ -24,6 +24,7 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
import static com.yahoo.text.Lowercase.toLowerCase;
@@ -333,7 +334,7 @@ public class Model implements Cloneable {
}
@Override
- public Object clone() {
+ public Model clone() {
try {
Model clone = (Model)super.clone();
if (queryTree != null)
@@ -349,19 +350,18 @@ public class Model implements Cloneable {
}
}
- public Model cloneFor(Query q) {
- Model model = (Model)this.clone();
- model.setParent(q);
+ public Model cloneFor(Query query) {
+ Model model = this.clone();
+ model.setParent(query);
return model;
}
- /** returns the query owning this, never null */
+ /** Returns the query owning this, never null */
public Query getParent() { return parent; }
/** Assigns the query owning this */
public void setParent(Query parent) {
- if (parent == null) throw new NullPointerException("A query models owner cannot be null");
- this.parent = parent;
+ this.parent = Objects.requireNonNull(parent, "A query models parent cannot be null");
}
/** Sets the set of sources this query will search from a comma-separated string of source names */
diff --git a/container-search/src/main/java/com/yahoo/search/query/Ranking.java b/container-search/src/main/java/com/yahoo/search/query/Ranking.java
index a5f4d3e37ff..19c1034667a 100644
--- a/container-search/src/main/java/com/yahoo/search/query/Ranking.java
+++ b/container-search/src/main/java/com/yahoo/search/query/Ranking.java
@@ -16,6 +16,8 @@ import com.yahoo.search.query.ranking.RankProperties;
import com.yahoo.search.query.ranking.SoftTimeout;
import com.yahoo.search.result.ErrorMessage;
+import java.util.Objects;
+
/**
* The ranking (hit ordering) settings of a query
*
@@ -69,7 +71,7 @@ public class Ranking implements Cloneable {
}
public static QueryProfileType getArgumentType() { return argumentType; }
- private final Query parent;
+ private Query parent;
/** The location of the query is used for distance ranking */
private Location location = null;
@@ -91,7 +93,7 @@ public class Ranking implements Cloneable {
private RankProperties rankProperties = new RankProperties();
- private RankFeatures rankFeatures = new RankFeatures();
+ private RankFeatures rankFeatures;
private MatchPhase matchPhase = new MatchPhase();
@@ -101,6 +103,7 @@ public class Ranking implements Cloneable {
public Ranking(Query parent) {
this.parent = parent;
+ this.rankFeatures = new RankFeatures(this);
}
/**
@@ -201,15 +204,59 @@ public class Ranking implements Cloneable {
/** Returns the soft timeout settings of this. This is never null. */
public SoftTimeout getSoftTimeout() { return softTimeout; }
+ /** Returns the sorting spec of this query, or null if none is set */
+ public Sorting getSorting() { return sorting; }
+
+ /** Sets how this query should be sorted. Set to null to turn off explicit sorting. */
+ public void setSorting(Sorting sorting) { this.sorting = sorting; }
+
+ /** Sets sorting from a string. See {@link Sorting} on syntax */
+ public void setSorting(String sortingString) {
+ if (sortingString == null)
+ setSorting((Sorting)null);
+ else
+ setSorting(new Sorting(sortingString));
+ }
+
+ public static Ranking getFrom(Query q) {
+ return (Ranking) q.properties().get(argumentTypeName);
+ }
+
+ public void prepare() {
+ rankFeatures.prepare(rankProperties);
+ matchPhase.prepare(rankProperties);
+ matching.prepare(rankProperties);
+ softTimeout.prepare(rankProperties);
+ prepareNow(freshness);
+ if (rerankCount != null)
+ rankProperties.put("vespa.hitcollector.heapsize", rerankCount);
+ }
+
+ private void prepareNow(Freshness freshness) {
+ if (freshness == null) return;
+ // TODO: See what freshness is doing with the internal props and simplify
+ if (rankProperties.get("vespa.now") == null || rankProperties.get("vespa.now").isEmpty()) {
+ rankProperties.put("vespa.now", "" + freshness.getRefTime());
+ }
+ }
+
+ /** Assigns the query owning this */
+ private void setParent(Query parent) {
+ this.parent = Objects.requireNonNull(parent, "A ranking objects parent cannot be null");
+ }
+
+ /** Returns the query owning this, never null */
+ public Query getParent() { return parent; }
+
@Override
- public Object clone() {
+ public Ranking clone() {
try {
Ranking clone = (Ranking) super.clone();
if (sorting != null) clone.sorting = this.sorting.clone();
clone.rankProperties = this.rankProperties.clone();
- clone.rankFeatures = this.rankFeatures.clone();
+ clone.rankFeatures = this.rankFeatures.cloneFor(clone);
clone.matchPhase = this.matchPhase.clone();
clone.matching = this.matching.clone();
clone.softTimeout = this.softTimeout.clone();
@@ -220,6 +267,12 @@ public class Ranking implements Cloneable {
}
}
+ public Ranking cloneFor(Query parent) {
+ Ranking ranking = this.clone();
+ ranking.setParent(parent);
+ return ranking;
+ }
+
@Override
public boolean equals(Object o) {
if (o == this) return true;
@@ -238,49 +291,7 @@ public class Ranking implements Cloneable {
@Override
public int hashCode() {
- int hash = 0;
- hash += 11 * rankFeatures.hashCode();
- hash += 13 * rankProperties.hashCode();
- hash += 17 * matchPhase.hashCode();
- hash += 19 * softTimeout.hashCode();
- hash += 23 * matching.hashCode();
- return Ranking.class.hashCode() + QueryHelper.combineHash(sorting,location,profile,hash);
- }
-
- /** Returns the sorting spec of this query, or null if none is set */
- public Sorting getSorting() { return sorting; }
-
- /** Sets how this query should be sorted. Set to null to turn off explicit sorting. */
- public void setSorting(Sorting sorting) { this.sorting = sorting; }
-
- /** Sets sorting from a string. See {@link Sorting} on syntax */
- public void setSorting(String sortingString) {
- if (sortingString == null)
- setSorting((Sorting)null);
- else
- setSorting(new Sorting(sortingString));
- }
-
- public static Ranking getFrom(Query q) {
- return (Ranking) q.properties().get(argumentTypeName);
- }
-
- public void prepare() {
- rankFeatures.prepare(rankProperties);
- matchPhase.prepare(rankProperties);
- matching.prepare(rankProperties);
- softTimeout.prepare(rankProperties);
- prepareNow(freshness);
- if (rerankCount != null)
- rankProperties.put("vespa.hitcollector.heapsize", rerankCount);
- }
-
- private void prepareNow(Freshness freshness) {
- if (freshness == null) return;
- // TODO: See what freshness is doing with the internal props and simplify
- if (rankProperties.get("vespa.now") == null || rankProperties.get("vespa.now").isEmpty()) {
- rankProperties.put("vespa.now", "" + freshness.getRefTime());
- }
+ return Objects.hash(rankFeatures, rankProperties, matchPhase, softTimeout, matching, sorting, location, profile);
}
}
diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/types/FieldDescription.java b/container-search/src/main/java/com/yahoo/search/query/profile/types/FieldDescription.java
index a0f38f61672..f30a3cc5ae6 100644
--- a/container-search/src/main/java/com/yahoo/search/query/profile/types/FieldDescription.java
+++ b/container-search/src/main/java/com/yahoo/search/query/profile/types/FieldDescription.java
@@ -4,10 +4,8 @@ package com.yahoo.search.query.profile.types;
import com.google.common.collect.ImmutableList;
import com.yahoo.processing.request.CompoundName;
import com.yahoo.search.query.profile.QueryProfile;
-import com.yahoo.tensor.TensorType;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
/**
diff --git a/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java b/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java
index 7d43c09f6fb..1a4ecb4ecd8 100644
--- a/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java
+++ b/container-search/src/main/java/com/yahoo/search/query/ranking/RankFeatures.java
@@ -2,6 +2,8 @@
package com.yahoo.search.query.ranking;
import com.yahoo.fs4.MapEncoder;
+import com.yahoo.search.Query;
+import com.yahoo.search.query.Ranking;
import com.yahoo.tensor.Tensor;
import com.yahoo.text.JSON;
@@ -20,13 +22,21 @@ import java.util.OptionalDouble;
*/
public class RankFeatures implements Cloneable {
+ private final Ranking parent;
private final Map<String, Object> features;
+ /** @deprecated pass a query */
+ @Deprecated // TODO: Remove on Vespa 8
public RankFeatures() {
- this(new LinkedHashMap<>());
+ this(new Ranking(new Query()));
+ }
+
+ public RankFeatures(Ranking parent) {
+ this(parent, new LinkedHashMap<>());
}
- private RankFeatures(Map<String, Object> features) {
+ private RankFeatures(Ranking parent, Map<String, Object> features) {
+ this.parent = parent;
this.features = features;
}
@@ -148,7 +158,11 @@ public class RankFeatures implements Cloneable {
@Override
public RankFeatures clone() {
- return new RankFeatures(new LinkedHashMap<>(features));
+ return new RankFeatures(parent, new LinkedHashMap<>(features));
+ }
+
+ public RankFeatures cloneFor(Ranking parent) {
+ return new RankFeatures(parent, new LinkedHashMap<>(features));
}
@Override
diff --git a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java
index a1556aac189..20678f3b7bb 100644
--- a/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/profile/types/test/QueryProfileTypeTestCase.java
@@ -20,6 +20,7 @@ import com.yahoo.search.query.profile.types.FieldType;
import com.yahoo.search.query.profile.types.QueryProfileType;
import com.yahoo.search.query.profile.types.QueryProfileTypeRegistry;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import java.net.URLEncoder;
@@ -423,6 +424,49 @@ public class QueryProfileTypeTestCase {
assertEquals(Tensor.from(tensorString), query.getRanking().getFeatures().getTensor("query(myTensor1)").get());
}
+ @Test
+ public void testTensorRankFeatureSetProgrammatically() {
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(testtype);
+ registry.register(profile);
+
+ CompiledQueryProfileRegistry cRegistry = registry.compile();
+ String tensorString = "{{a:a1, b:b1}:1.0, {a:a2, b:b1}:2.0}}";
+ Query query = new Query(HttpRequest.createTestRequest("?", com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cRegistry.getComponent("test"));
+ query.properties().set("ranking.features.query(myTensor1)", Tensor.from(tensorString));
+ assertEquals(Tensor.from(tensorString), query.getRanking().getFeatures().getTensor("query(myTensor1)").get());
+ }
+
+ @Test
+ @Ignore
+ public void testTensorRankFeatureSetProgrammaticallyWithWrongType() {
+ QueryProfile profile = new QueryProfile("test");
+ profile.setType(testtype);
+ registry.register(profile);
+
+ CompiledQueryProfileRegistry cRegistry = registry.compile();
+ String tensorString = "tensor(x[3]):[0.1, 0.2, 0.3]";
+ Query query = new Query(HttpRequest.createTestRequest("?", com.yahoo.jdisc.http.HttpRequest.Method.GET),
+ cRegistry.getComponent("test"));
+ try {
+ query.getRanking().getFeatures().put("query(myTensor1)",Tensor.from(tensorString));
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertEquals("'query(myTensor1)' must be of type tensor(a{},b{}) but was of type tensor(x[3])",
+ e.getMessage());
+ }
+ try {
+ query.properties().set("ranking.features.query(myTensor1)", Tensor.from(tensorString));
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertEquals("'query(myTensor1)' must be of type tensor(a{},b{}) but was of type tensor(x[3])",
+ e.getMessage());
+ }
+ }
+
// Expected to work exactly as testTensorRankFeatureInRequest
@Test
public void testTensorRankFeatureInRequestWithInheritedQueryProfileType() {
diff --git a/container-search/src/test/java/com/yahoo/search/query/test/RankFeaturesTestCase.java b/container-search/src/test/java/com/yahoo/search/query/test/RankFeaturesTestCase.java
index 8848e33c365..0644a2b02e8 100644
--- a/container-search/src/test/java/com/yahoo/search/query/test/RankFeaturesTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/query/test/RankFeaturesTestCase.java
@@ -2,6 +2,8 @@
package com.yahoo.search.query.test;
import com.yahoo.io.GrowableByteBuffer;
+import com.yahoo.search.Query;
+import com.yahoo.search.query.Ranking;
import com.yahoo.search.query.ranking.RankFeatures;
import com.yahoo.search.query.ranking.RankProperties;
import com.yahoo.tensor.Tensor;
@@ -36,11 +38,11 @@ public class RankFeaturesTestCase {
@Test
@SuppressWarnings("deprecation")
public void requireThatRankFeaturesUsingDoubleAndDoubleToStringEncodeTheSameWay() {
- RankFeatures withDouble = new RankFeatures();
+ RankFeatures withDouble = new RankFeatures(new Ranking(new Query()));
withDouble.put("query(myDouble)", 3.8);
assertEquals(3.8, withDouble.getDouble("query(myDouble)").getAsDouble(), 0.000001);
- RankFeatures withString = new RankFeatures();
+ RankFeatures withString = new RankFeatures(new Ranking(new Query()));
withString.put("query(myDouble)", String.valueOf(3.8));
RankProperties withDoubleP = new RankProperties();
@@ -99,7 +101,7 @@ public class RankFeaturesTestCase {
}
private static RankProperties createRankPropertiesWithTensors(List<Entry> entries) {
- RankFeatures features = new RankFeatures();
+ RankFeatures features = new RankFeatures(new Ranking(new Query()));
for (Entry entry : entries) {
features.put(entry.key, entry.tensor);
}