From ceaa06bd68b6c6bb87f347d8e375c85d1638ff1c Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Sun, 21 Jan 2024 22:18:21 +0100 Subject: Allow simple queries with negative terms only --- .../com/yahoo/prelude/query/parser/AllParser.java | 6 ++-- .../com/yahoo/prelude/query/parser/AnyParser.java | 14 ++++----- .../yahoo/prelude/query/parser/SimpleParser.java | 8 ++--- .../com/yahoo/prelude/query/parser/WebParser.java | 5 +-- .../prelude/query/parser/test/ParseTestCase.java | 36 ++++++++++++++++------ 5 files changed, 44 insertions(+), 25 deletions(-) (limited to 'container-search') 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 i = ((CompositeItem) root).getItemIterator(); i.hasNext();) { - markAllTermsAsFilters(i.next()); + if (root instanceof CompositeItem composite) { + for (Iterator 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 -- cgit v1.2.3