summaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/search/querytransform/WeakAndReplacementSearcher.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-search/src/main/java/com/yahoo/search/querytransform/WeakAndReplacementSearcher.java')
-rw-r--r--container-search/src/main/java/com/yahoo/search/querytransform/WeakAndReplacementSearcher.java66
1 files changed, 66 insertions, 0 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/querytransform/WeakAndReplacementSearcher.java b/container-search/src/main/java/com/yahoo/search/querytransform/WeakAndReplacementSearcher.java
new file mode 100644
index 00000000000..058f6b93ae3
--- /dev/null
+++ b/container-search/src/main/java/com/yahoo/search/querytransform/WeakAndReplacementSearcher.java
@@ -0,0 +1,66 @@
+package com.yahoo.search.querytransform;
+
+import com.yahoo.prelude.query.*;
+import com.yahoo.processing.request.CompoundName;
+import com.yahoo.search.Query;
+import com.yahoo.search.Result;
+import com.yahoo.search.Searcher;
+import com.yahoo.search.searchchain.Execution;
+
+/**
+ * Recursively replaces all instances of OrItems with WeakAndItems if the query property weakand.replace is true.
+ * Otherwise a noop searcher.
+ *
+ * @author karowan
+ */
+public class WeakAndReplacementSearcher extends Searcher {
+ private static final CompoundName WEAKAND_REPLACE = new CompoundName("weakAnd.replace");
+
+ @Override public Result search(Query query, Execution execution) {
+ if (!query.properties().getBoolean(WEAKAND_REPLACE)) {
+ return execution.search(query);
+ }
+ replaceOrItems(query);
+ return execution.search(query);
+ }
+
+ /**
+ * Extracts the queryTree root and the wand.hits property to send to the recursive replacement function
+ * @param query the search query
+ */
+ private void replaceOrItems(Query query) {
+ Item root = query.getModel().getQueryTree().getRoot();
+ int hits = query.properties().getInteger("wand.hits", WeakAndItem.defaultN);
+ query.getModel().getQueryTree().setRoot(replaceOrItems(root, hits));
+ if (root != query.getModel().getQueryTree().getRoot())
+ query.trace("Replaced OR by WeakAnd", true, 2);
+ }
+
+
+ /**
+ * Recursively iterates over an Item to replace all instances of OrItems with WeakAndItems
+ * @param item the current item in the replacement iteration
+ * @param hits the wand.hits property from the request which is assigned to the N value of the new WeakAndItem
+ * @return The original item or a WeakAndItem replacement of an OrItem
+ */
+ private Item replaceOrItems(Item item, int hits) {
+ if (!(item instanceof CompositeItem)) {
+ return item;
+ }
+ CompositeItem compositeItem = (CompositeItem) item;
+ if (compositeItem instanceof OrItem) {
+ WeakAndItem newItem = new WeakAndItem(hits);
+ newItem.setWeight(compositeItem.getWeight());
+ compositeItem.items().forEach(newItem::addItem);
+ compositeItem = newItem;
+ }
+ for (int i = 0; i < compositeItem.getItemCount(); i++) {
+ Item subItem = compositeItem.getItem(i);
+ Item replacedItem = replaceOrItems(subItem, hits);
+ if (replacedItem != subItem) {
+ compositeItem.setItem(i, replacedItem);
+ }
+ }
+ return compositeItem;
+ }
+}