summaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java')
-rw-r--r--container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java59
1 files changed, 51 insertions, 8 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java
index 826c9949bcf..accef7ba154 100644
--- a/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java
+++ b/container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java
@@ -10,6 +10,7 @@ import com.yahoo.search.query.profile.types.QueryProfileType;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -40,14 +41,12 @@ public class QueryProfileCompiler {
// Resolve values for each existing variant and combine into a single data structure
Set<DimensionBindingForPath> variants = collectVariants(CompoundName.empty, in, DimensionBinding.nullBinding);
variants.add(new DimensionBindingForPath(DimensionBinding.nullBinding, CompoundName.empty)); // if this contains no variants
- if (log.isLoggable(Level.FINE))
- log.fine("Compiling " + in.toString() + " having " + variants.size() + " variants");
- int i = 0;
+ log.fine(() -> "Compiling " + in.toString() + " having " + variants.size() + " variants");
for (DimensionBindingForPath variant : variants) {
- if (log.isLoggable(Level.FINER))
- log.finer(" Compiling variant " + i++ + ": " + variant);
- for (Map.Entry<String, Object> entry : in.listValues(variant.path(), variant.binding().getContext(), null).entrySet())
+ log.finer(() -> " Compiling variant " + variant);
+ for (Map.Entry<String, Object> entry : in.listValues(variant.path(), variant.binding().getContext(), null).entrySet()) {
values.put(variant.path().append(entry.getKey()), variant.binding(), entry.getValue());
+ }
for (Map.Entry<CompoundName, QueryProfileType> entry : in.listTypes(variant.path(), variant.binding().getContext()).entrySet())
types.put(variant.path().append(entry.getKey()), variant.binding(), entry.getValue());
for (CompoundName reference : in.listReferences(variant.path(), variant.binding().getContext()))
@@ -62,7 +61,7 @@ public class QueryProfileCompiler {
}
/**
- * Returns all the unique combinations of dimension values which have values set reachable from this profile.
+ * Returns all the unique combinations of dimension values which have values reachable from this profile.
*
* @param profile the profile we are collecting the variants of
* @param currentVariant the variant we must have to arrive at this point in the query profile graph
@@ -74,15 +73,59 @@ public class QueryProfileCompiler {
if (profile instanceof BackedOverridableQueryProfile)
variants.addAll(collectVariantsInThis(path, ((BackedOverridableQueryProfile) profile).getBacking(), currentVariant));
- Set<DimensionBindingForPath> parentVariants = new HashSet<>();
+ Set<DimensionBindingForPath> parentVariants;
for (QueryProfile inheritedProfile : profile.inherited()) {
parentVariants = collectVariants(path, inheritedProfile, currentVariant);
variants.addAll(parentVariants);
variants.addAll(combined(variants, parentVariants)); // parents and children may have different variant dimensions
}
+
+ variants.addAll(leftExpanded(variants));
return variants;
}
+ /**
+ * For variants which are underspecified on the left we must explicitly resolve each possible combination
+ * of actual left-side values.
+ *
+ * I.e if we have the variants [-,b=b1], [a=a1,-], [a=a2,-],
+ * this returns the variants [a=a1,b=b1], [a=a2,b=b1]
+ *
+ * This is necessary because left-specified values takes precedence, such that resolving [a=a1,b=b1] would
+ * lead us to the compiled profile [a=a1,-], which may contain default values for properties where
+ * we should have preferred variant values in [-,b=b1].
+ */
+ private static Set<DimensionBindingForPath> leftExpanded(Set<DimensionBindingForPath> variants) {
+ Set<DimensionBindingForPath> expanded = new HashSet<>();
+ for (var variant : variants) {
+ if (hasLeftWildcard(variant.binding()))
+ expanded.addAll(leftExpanded(variant, variants));
+ }
+ return expanded;
+ }
+
+ private static boolean hasLeftWildcard(DimensionBinding variant) {
+ for (int i = 0; i < variant.getValues().size() - 1; i++) { // -1 to not check the rightmost
+ if (variant.getValues().get(i) == null)
+ return true;
+ }
+ return false;
+ }
+
+ private static Set<DimensionBindingForPath> leftExpanded(DimensionBindingForPath variantToExpand,
+ Set<DimensionBindingForPath> variants) {
+ Set<DimensionBindingForPath> expanded = new HashSet<>();
+ for (var variant : variants) {
+ if ( ! variantToExpand.path().equals(variant.path())) continue;
+
+ DimensionBinding combined = variantToExpand.binding().combineWith(variant.binding);
+ if ( ! combined.isInvalid() )
+ expanded.add(new DimensionBindingForPath(combined, variantToExpand.path()));
+ }
+ return expanded;
+ }
+
+
/** Generates a set of all the (legal) combinations of the variants in the given sets */
private static Set<DimensionBindingForPath> combined(Set<DimensionBindingForPath> v1s,
Set<DimensionBindingForPath> v2s) {