aboutsummaryrefslogtreecommitdiffstats
path: root/container-search
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@vespa.ai>2024-01-21 22:18:21 +0100
committerJon Bratseth <bratseth@vespa.ai>2024-01-21 22:18:21 +0100
commitceaa06bd68b6c6bb87f347d8e375c85d1638ff1c (patch)
treee32e3974a4fcfaf83622a0ea5836c496e4d94f69 /container-search
parentc973b6f20f29eb39cd35ab8782421dbbc2688504 (diff)
Allow simple queries with negative terms only
Diffstat (limited to 'container-search')
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java6
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java14
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java8
-rw-r--r--container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java5
-rw-r--r--container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java36
5 files changed, 44 insertions, 25 deletions
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java
index 0010291de66..43bd175b348 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/AllParser.java
@@ -11,6 +11,7 @@ import com.yahoo.prelude.query.OrItem;
import com.yahoo.prelude.query.PhraseItem;
import com.yahoo.prelude.query.QueryCanonicalizer;
import com.yahoo.prelude.query.RankItem;
+import com.yahoo.prelude.query.TrueItem;
import com.yahoo.prelude.query.WeakAndItem;
import com.yahoo.search.query.QueryTree;
import com.yahoo.search.query.parser.ParserEnvironment;
@@ -79,8 +80,8 @@ public class AllParser extends SimpleParser {
// Combine the items
Item topLevel = and;
- if (not != null && topLevel != null) {
- not.setPositiveItem(topLevel);
+ if (not != null) {
+ not.setPositiveItem(topLevel != null ? topLevel : new TrueItem());
topLevel = not;
}
@@ -130,6 +131,7 @@ public class AllParser extends SimpleParser {
if ( ! tokens.skip(MINUS)) return null;
if (tokens.currentIsNoIgnore(SPACE)) return null;
var itemAndExplicitIndex = indexableItem();
+
item = itemAndExplicitIndex.getFirst();
boolean explicitIndex = itemAndExplicitIndex.getSecond();
if (item == null) {
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java
index efc804fcf1f..1bbc21768b5 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/AnyParser.java
@@ -12,6 +12,7 @@ import com.yahoo.prelude.query.OrItem;
import com.yahoo.prelude.query.PhraseItem;
import com.yahoo.prelude.query.RankItem;
import com.yahoo.prelude.query.TermItem;
+import com.yahoo.prelude.query.TrueItem;
import com.yahoo.search.query.parser.ParserEnvironment;
import java.util.Iterator;
@@ -106,9 +107,8 @@ public class AnyParser extends SimpleParser {
}
return rank;
} else if ((topLevelItem instanceof RankItem)
- && (item instanceof RankItem)
+ && (item instanceof RankItem itemAsRank)
&& (((RankItem) item).getItem(0) instanceof OrItem)) {
- RankItem itemAsRank = (RankItem) item;
OrItem or = (OrItem) itemAsRank.getItem(0);
((RankItem) topLevelItem).addItem(0, or);
@@ -139,8 +139,10 @@ public class AnyParser extends SimpleParser {
if (root instanceof PhraseItem) {
root.setFilter(true);
}
- for (Iterator<Item> i = ((CompositeItem) root).getItemIterator(); i.hasNext();) {
- markAllTermsAsFilters(i.next());
+ if (root instanceof CompositeItem composite) {
+ for (Iterator<Item> i = composite.getItemIterator(); i.hasNext(); ) {
+ markAllTermsAsFilters(i.next());
+ }
}
}
}
@@ -206,8 +208,7 @@ public class AnyParser extends SimpleParser {
return root;
}
- if (root instanceof RankItem) {
- RankItem rootAsRank = (RankItem) root;
+ if (root instanceof RankItem rootAsRank) {
Item firstChild = rootAsRank.getItem(0);
if (firstChild instanceof NotItem) {
@@ -228,7 +229,6 @@ public class AnyParser extends SimpleParser {
}
NotItem not = new NotItem();
-
not.addPositiveItem(root);
not.addNegativeItem(item);
return not;
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java
index deab2be9d00..962d722d3a9 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/SimpleParser.java
@@ -79,6 +79,7 @@ abstract class SimpleParser extends StructuredParser {
not = new NotItem();
not.addNegativeItem(item);
topLevelItem = combineItems(topLevelItem, not);
+ System.out.println("not : " + not + " not poisitve: " + not.getPositiveItem());
} else {
not.addNegativeItem(item);
}
@@ -130,14 +131,13 @@ abstract class SimpleParser extends StructuredParser {
}
}
if (not != null && not.getPositiveItem() instanceof TrueItem) {
- // Incomplete not, only negatives -
-
+ // Incomplete not, only negatives - simplify when possible
if (topLevelItem != null && topLevelItem != not) {
// => neutral rank items becomes implicit positives
not.addPositiveItem(getItemAsPositiveItem(topLevelItem, not));
return not;
- } else { // Only negatives - ignore them
- return null;
+ } else {
+ return not;
}
}
if (topLevelItem != null) {
diff --git a/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java b/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java
index 06ea583c53f..75396a8714f 100644
--- a/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java
+++ b/container-search/src/main/java/com/yahoo/prelude/query/parser/WebParser.java
@@ -6,6 +6,7 @@ import com.yahoo.prelude.query.CompositeItem;
import com.yahoo.prelude.query.Item;
import com.yahoo.prelude.query.NotItem;
import com.yahoo.prelude.query.OrItem;
+import com.yahoo.prelude.query.TrueItem;
import com.yahoo.prelude.query.WordItem;
import com.yahoo.search.query.parser.ParserEnvironment;
@@ -69,8 +70,8 @@ public class WebParser extends AllParser {
if (or != null)
topLevel = or;
- if (not != null && topLevel != null) {
- not.setPositiveItem(topLevel);
+ if (not != null) {
+ not.setPositiveItem(topLevel != null ? topLevel : new TrueItem());
topLevel = not;
}
diff --git a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java
index 4383be184fa..156c34e5005 100644
--- a/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java
+++ b/container-search/src/test/java/com/yahoo/prelude/query/parser/test/ParseTestCase.java
@@ -21,6 +21,7 @@ import com.yahoo.prelude.query.RankItem;
import com.yahoo.prelude.query.SubstringItem;
import com.yahoo.prelude.query.SuffixItem;
import com.yahoo.prelude.query.TaggableItem;
+import com.yahoo.prelude.query.TrueItem;
import com.yahoo.prelude.query.WordItem;
import com.yahoo.language.process.SpecialTokens;
import com.yahoo.prelude.query.parser.TestLinguistics;
@@ -262,17 +263,28 @@ public class ParseTestCase {
@Test
void testNotOnly() {
- tester.assertParsed(null, "-foobar", Query.Type.ALL);
+ Item item = tester.assertParsed("-foobar", "-foobar", Query.Type.ALL);
+ assertTrue(item instanceof NotItem);
+ assertTrue(((NotItem) item).getPositiveItem() instanceof TrueItem);
}
@Test
- void testMultipleNotsOnlt() {
- tester.assertParsed(null, "-foo -bar -foobar", Query.Type.ALL);
+ void testNotOnlyAny() {
+ Item item = tester.assertParsed("-foobar", "-foobar", Query.Type.ANY);
+ assertTrue(item instanceof NotItem);
+ assertTrue(((NotItem) item).getPositiveItem() instanceof TrueItem);
+ }
+
+ @Test
+ void testMultipleNotsOnly() {
+ Item item = tester.assertParsed("-foo -bar -foobar", "-foo -bar -foobar", Query.Type.ALL);
+ assertTrue(item instanceof NotItem);
+ assertTrue(((NotItem) item).getPositiveItem() instanceof TrueItem);
}
@Test
void testOnlyNotComposite() {
- tester.assertParsed(null, "-(foo bar baz)", Query.Type.ALL);
+ tester.assertParsed("-(AND foo bar baz)", "-(foo bar baz)", Query.Type.ALL);
}
@Test
@@ -391,7 +403,7 @@ public class ParseTestCase {
@Test
void testMinusAndPluses() {
- tester.assertParsed(null, "--test+-if", Query.Type.ANY);
+ tester.assertParsed("-(AND test if)", "--test+-if", Query.Type.ANY);
}
@Test
@@ -1305,7 +1317,9 @@ public class ParseTestCase {
@Test
void testNotFilterEmptyQuery() {
- tester.assertParsed(null, "", "-foo", Query.Type.ANY);
+ Item item = tester.assertParsed("-|foo", "", "-foo", Query.Type.ANY);
+ assertTrue(item instanceof NotItem);
+ assertTrue(((NotItem) item).getPositiveItem() instanceof TrueItem);
}
@Test
@@ -1380,7 +1394,7 @@ public class ParseTestCase {
@Test
void testMultitermNotFilterEmptyQuery() {
- tester.assertParsed(null, "", "-foo -foz", Query.Type.ANY);
+ tester.assertParsed("-|foo -|foz", "", "-foo -foz", Query.Type.ANY);
}
@Test
@@ -2320,17 +2334,19 @@ public class ParseTestCase {
@Test
void testNotOnlyWeb() {
- tester.assertParsed(null, "-foobar", Query.Type.WEB);
+ Item item = tester.assertParsed("-foobar", "-foobar", Query.Type.WEB);
+ assertTrue(item instanceof NotItem);
+ assertTrue(((NotItem)item).getPositiveItem() instanceof TrueItem);
}
@Test
void testMultipleNotsOnltWeb() {
- tester.assertParsed(null, "-foo -bar -foobar", Query.Type.WEB);
+ tester.assertParsed("-foo -bar -foobar", "-foo -bar -foobar", Query.Type.WEB);
}
@Test
void testOnlyNotCompositeWeb() {
- tester.assertParsed(null, "-(foo bar baz)", Query.Type.WEB);
+ tester.assertParsed("-(AND foo bar baz)", "-(foo bar baz)", Query.Type.WEB);
}
@Test