diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /container-search/src/main/java/com/yahoo/search/query/ranking/Diversity.java |
Publish
Diffstat (limited to 'container-search/src/main/java/com/yahoo/search/query/ranking/Diversity.java')
-rw-r--r-- | container-search/src/main/java/com/yahoo/search/query/ranking/Diversity.java | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/query/ranking/Diversity.java b/container-search/src/main/java/com/yahoo/search/query/ranking/Diversity.java new file mode 100644 index 00000000000..b1865ad9d75 --- /dev/null +++ b/container-search/src/main/java/com/yahoo/search/query/ranking/Diversity.java @@ -0,0 +1,127 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.search.query.ranking; + +import com.yahoo.search.query.Ranking; +import com.yahoo.search.query.profile.types.FieldDescription; +import com.yahoo.search.query.profile.types.QueryProfileType; + +import java.util.Objects; + +/** + * <p>The diversity settings during match phase of a query. + * These are the same settings for diversity during match phase that can be set in a rank profile + * and is used for achieving guaranteed diversity at the cost of slightly higher cost as more hits must be + * considered compared to plain match-phase.</p> + * + * <p>You specify an additional attribute to be the diversifier and also min diversity needed.</p> + * + * @author <a href="mailto:balder@yahoo-inc.com">Henning Baldersheim</a> + */ +public class Diversity implements Cloneable { + + /** The type representing the property arguments consumed by this */ + private static final QueryProfileType argumentType; + + public static final String ATTRIBUTE = "attribute"; + public static final String MINGROUPS = "minGroups"; + public static final String CUTOFF = "cutoff"; + public static final String FACTOR = "factor"; + public static final String STRATEGY = "strategy"; + + + static { + argumentType =new QueryProfileType(Ranking.DIVERSITY); + argumentType.setStrict(true); + argumentType.setBuiltin(true); + argumentType.addField(new FieldDescription(ATTRIBUTE, "string")); + argumentType.addField(new FieldDescription(MINGROUPS, "long")); + argumentType.freeze(); + } + public static QueryProfileType getArgumentType() { return argumentType; } + + public enum CutoffStrategy {loose, strict}; + private String attribute = null; + private Long minGroups = null; + private Double cutoffFactor = null; + private CutoffStrategy cutoffStrategy= null; + + /** + * Sets the attribute field which will be used to guarantee diversity. + * Set to null (default) to disable diversification. + * <p> + * If this is set, make sure to also set the maxGroups value. + * <p> + * This attribute must be singlevalue. + */ + public void setAttribute(String attribute) { this.attribute = attribute; } + + /** Returns the attribute to use for diversity, or null if none */ + public String getAttribute() { return attribute; } + + /** + * Sets the max hits to aim for producing in the match phase. + * This must be set if an attribute value is set. + * It should be set to a reasonable fraction of the total documents on each partition. + */ + public void setMinGroups(long minGroups) { this.minGroups = minGroups; } + + /** Returns the max hits to aim for producing in the match phase on each content node, or null if not set */ + public Long getMinGroups() { return minGroups; } + + public void setCutoffFactor(double cutoffFactor) { this.cutoffFactor = cutoffFactor; } + public Double getCutoffFactor() { return cutoffFactor; } + public void setCutoffStrategy(String cutoffStrategy) { this.cutoffStrategy = CutoffStrategy.valueOf(cutoffStrategy); } + public CutoffStrategy getCutoffStrategy() { return cutoffStrategy; } + + /** Internal operation - DO NOT USE */ + public void prepare(RankProperties rankProperties) { + if (attribute == null && minGroups == null) return; + + if (attribute != null && !attribute.isEmpty()) { + rankProperties.put("vespa.matchphase.diversity.attribute", attribute); + } + if (minGroups != null) { + rankProperties.put("vespa.matchphase.diversity.mingroups", String.valueOf(minGroups)); + } + if (cutoffFactor != null) { + rankProperties.put("vespa.matchphase.diversity.cutoff.factor", String.valueOf(cutoffFactor)); + } + if (cutoffStrategy != null) { + rankProperties.put("vespa.matchphase.diversity.cutoff.strategy", cutoffStrategy); + } + } + + @Override + public Diversity clone() { + try { + return (Diversity)super.clone(); + } + catch (CloneNotSupportedException e) { + throw new RuntimeException("Won't happen", e); + } + } + + @Override + public int hashCode() { + int hash = 0; + if (attribute != null) hash += 11 * attribute.hashCode(); + if (minGroups != null) hash += 13 * minGroups.hashCode(); + if (cutoffFactor != null) hash += 17 * cutoffFactor.hashCode(); + if (cutoffStrategy != null) hash += 19 * cutoffStrategy.hashCode(); + return hash; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if ( ! (o instanceof Diversity)) return false; + + Diversity other = (Diversity)o; + if ( ! Objects.equals(this.attribute, other.attribute)) return false; + if ( ! Objects.equals(this.minGroups, other.minGroups)) return false; + if ( ! Objects.equals(this.cutoffFactor, other.cutoffFactor)) return false; + if ( ! Objects.equals(this.cutoffStrategy, other.cutoffStrategy)) return false; + return true; + } + +} |