def test_named_queries_group(self): tree = SearchField("text", FieldGroup(Word("bar"))) set_name(tree.children[0], "a") result = self.transformer(tree) self.assertEqual( result, {"term": { "text": { "value": "bar", "_name": "a" } }}, ) tree = Group(SearchField("text", Word("bar"))) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, {"term": { "text": { "value": "bar", "_name": "a" } }}, )
def test_set_children_raises(self): test = self._test_set_children_raises test(Word("foo"), [Word("foo")]) test(Phrase('"foo"'), [Word("foo")]) test(Regex("/foo/"), [Word("foo")]) test(SearchField("foo", Word("bar")), []) test(SearchField("foo", Word("bar")), [Word("bar"), Word("baz")]) test(Group(Word("foo")), []) test(Group(Word("foo")), [Word("foo"), Word("bar")]) test(FieldGroup(Word("foo")), []) test(FieldGroup(Word("foo")), [Word("foo"), Word("bar")]) test(Range(Word("20"), Word("30")), []) test(Range(Word("20"), Word("30")), [Word("20"), Word("30"), Word("40")]) test(Proximity(Word("foo")), []) test(Proximity(Word("foo")), [Word("foo"), Word("bar")]) test(Fuzzy(Word("foo")), []) test(Fuzzy(Word("foo")), [Word("foo"), Word("bar")]) test(Boost(Word("foo"), force=1), []) test(Boost(Word("foo"), force=1), [Word("foo"), Word("bar")]) test(Plus(Word("foo")), []) test(Plus(Word("foo")), [Word("foo"), Word("bar")]) test(Not(Word("foo")), []) test(Not(Word("foo")), [Word("foo"), Word("bar")]) test(Prohibit(Word("foo")), []) test(Prohibit(Word("foo")), [Word("foo"), Word("bar")])
def test_named_queries_term(self): tree = SearchField("text", Word("bar")) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, {"term": { "text": { "value": "bar", "_name": "a" } }}, ) tree = SearchField("text", Phrase('"foo bar"')) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, {"term": { "text": { "value": "foo bar", "_name": "a" } }}, )
def test_named_queries_unknown(self): tree = UnknownOperation(SearchField("text", Word("foo")), SearchField("spam", Word("bar"))) set_name(tree.operands[0], "a") set_name(tree.operands[1], "b") result = self.transformer(tree) self.assertEqual( result, { 'bool': { 'should': [{ 'term': { 'text': { '_name': 'a', 'value': 'foo' } } }, { 'match': { 'spam': { '_name': 'b', 'query': 'bar', 'zero_terms_query': 'none' } } }] } })
def test_named_queries_match(self): tree = SearchField("spam", Word("bar")) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, { "match": { "spam": { "query": "bar", "_name": "a", "zero_terms_query": "none", }, }, }, ) tree = SearchField("spam", Phrase('"foo bar"')) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, { "match_phrase": { "spam": { "query": "foo bar", "_name": "a", }, }, }, )
def test_named_queries_not(self): tree = Not(SearchField("text", Word("foo"))) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, { 'bool': { 'must_not': [{ 'term': { 'text': { '_name': 'a', 'value': 'foo' } } }] } }) tree = Prohibit(SearchField("text", Word("foo"))) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, { 'bool': { 'must_not': [{ 'term': { 'text': { '_name': 'a', 'value': 'foo' } } }] } })
def test_datemath_in_field(self): tree = SearchField("foo", Word(r"2015-12-19||+2\d")) parsed = parser.parse(r'foo:2015-12-19||+2\d') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Word(r"now+2h+20m\h")) parsed = parser.parse(r'foo:now+2h+20m\h') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed)
def test_auto_name_nested(self): tree = AndOperation( OrOperation( SearchField("bar", Word("test")), AndOperation( Proximity(Phrase('"test"'), 2), SearchField("baz", Word("test")), ), ), Group(UnknownOperation( Fuzzy(Word("test")), Phrase('"test"'), ), ), ) names = auto_name(tree) self.assertEqual(sorted(names.keys()), list("abcdefgh")) # and and1 = tree self.assertEqual(get_name(and1), None) # - or or1 = and1.children[0] self.assertEqual(get_name(or1), "a") self.assertEqual(names["a"], (0, )) # -- search field sfield1 = or1.children[0] self.assertEqual(get_name(sfield1), "c") self.assertEqual(names["c"], (0, 0)) self.assertEqual(get_name(sfield1.expr), None) # -- and and2 = or1.children[1] self.assertEqual(get_name(and2), "d") self.assertEqual(names["d"], (0, 1)) # --- proximity phrase self.assertEqual(get_name(and2.children[0]), "e") self.assertEqual(names["e"], (0, 1, 0)) self.assertEqual(get_name(and2.children[0].term), None) # --- search field sfield2 = and2.children[1] self.assertEqual(get_name(sfield2), "f") self.assertEqual(names["f"], (0, 1, 1)) self.assertEqual(get_name(sfield2.expr), None) # - group group1 = and1.children[1] self.assertEqual(get_name(group1), "b") self.assertEqual(names["b"], (1, )) # -- unknown op unknownop1 = group1.children[0] self.assertEqual(get_name(unknownop1), None) # --- fuzzy word self.assertEqual(get_name(unknownop1.children[0]), "g") self.assertEqual(names["g"], (1, 0, 0)) self.assertEqual(get_name(unknownop1.children[0].term), None) # --- phrase self.assertEqual(get_name(unknownop1.children[1]), "h") self.assertEqual(names["h"], (1, 0, 1))
def test_range(self): tree = (AndOperation( SearchField("foo", Range(Word("10", tail=" "), Word("100", head=" "), True, True), tail=" "), SearchField("bar", Range(Word("a*", tail=" "), Word("*", head=" "), True, False), head=" "))) parsed = parser.parse('foo:[10 TO 100] AND bar:[a* TO *}') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_named_queries_complex(self): tree = (AndOperation( SearchField("text", Phrase('"foo bar"')), Group(OrOperation( Word("bar"), SearchField("spam", Word("baz")), ), ), )) and_op = tree search_text = and_op.operands[0] or_op = and_op.operands[1].children[0] bar = or_op.operands[0] search_spam = or_op.operands[1] set_name(search_text, "foo_bar") set_name(bar, "bar") set_name(search_spam, "baz") expected = { 'bool': { 'must': [{ 'term': { 'text': { '_name': 'foo_bar', 'value': 'foo bar' } } }, { 'bool': { 'should': [{ 'term': { 'text': { '_name': 'bar', 'value': 'bar' } } }, { 'match': { 'spam': { '_name': 'baz', 'query': 'baz', 'zero_terms_query': 'none' } } }] } }] } } result = self.transformer(tree) self.assertEqual(result, expected)
def test_search_field(self): orig = SearchField(name="foo", expr=Word("bar"), pos=3, head="\n", tail="\t") copy = orig.clone_item() self.assert_equal_tail_head_pos(orig, copy) self.assertEqual(orig.name, copy.name) self.assertEqual(copy.expr, NONE_ITEM) self.assertNotEqual(orig, copy) copy.children = [Word("bar")] self.assertEqual(orig, copy)
def visit_phrase(self, node, parent): if (len(parent) > 0 and (isinstance(parent[-1], luqum.tree.SearchField) or isinstance(parent[-1], luqum.tree.Range))): return node else: search_list = [SearchField(f, node) for f in self.fields] return Group(OrOperation(*search_list))
def test_bad_group(self): check = LuceneCheck() query = SearchField("f", Group(Word("foo"))) self.assertFalse(check(query)) self.assertEqual(len(check.errors(query)), 2) # one for bad expr, one for misuse self.assertIn("Group misuse", "".join(check.errors(query)))
def test_auto_name_nested(self): tree = AndOperation( OrOperation( SearchField("bar", Word("test")), AndOperation( Proximity(Phrase('"test"'), 2), SearchField("baz", Word("test")), ), ), Group( UnknownOperation( Fuzzy(Word("test")), Phrase('"test"'), ), ), ) auto_name(tree) # and and1 = tree self.assertEqual(get_name(and1), "0") # - or or1 = and1.children[0] self.assertEqual(get_name(or1), "0_0") # --- search field word sfield1 = or1.children[0] self.assertFalse(get_name(sfield1)) self.assertEqual(get_name(sfield1.expr), "0_0_0") # --- and and2 = or1.children[1] self.assertEqual(get_name(and2), "0_0_1") # ----- proximity phrase self.assertEqual(get_name(and2.children[0].term), "0_0_1_0") # ----- search field word sfield2 = and2.children[1] self.assertFalse(get_name(sfield2)) self.assertEqual(get_name(sfield2.expr), "0_0_1_1") # - group group1 = and1.children[1] self.assertEqual(get_name(group1), None) # --- unknown op unknownop1 = group1.children[0] self.assertEqual(get_name(unknownop1), "0_1") # ----- fuzzy word self.assertEqual(get_name(unknownop1.children[0].term), "0_1_0") # ----- phrase self.assertEqual(get_name(unknownop1.children[1]), "0_1_1")
def test_date_in_field(self): tree = SearchField("foo", Word("2015-12-19")) parsed = parser.parse('foo:2015-12-19') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Word("2015-12-19T22:30")) parsed = parser.parse('foo:2015-12-19T22:30') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Word("2015-12-19T22:30:45")) parsed = parser.parse('foo:2015-12-19T22:30:45') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Word("2015-12-19T22:30:45.234Z")) parsed = parser.parse('foo:2015-12-19T22:30:45.234Z') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed)
def test_combinations(self): # self.assertEqual(parser.parse("subject:test desc:(house OR car)").pval, "") tree = (UnknownOperation( SearchField("subject", Word("test"), tail=" "), AndOperation( SearchField("desc", FieldGroup( OrOperation(Word("house", tail=" "), Word("car", head=" "))), tail=" "), Not(Proximity(Phrase('"approximatly this"'), 3, head=" "), head=" ")))) parsed = parser.parse( 'subject:test desc:(house OR car) AND NOT "approximatly this"~3') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_flavours(self): tree = SearchField( "somedate", Range(Word("now/d-1d+7H", tail=" "), Word("now/d+7H", head=" "), True, True)) parsed = parser.parse('somedate:[now/d-1d+7H TO now/d+7H]') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_date_in_range(self): # juste one funky expression tree = SearchField( "foo", Range(Word(r"2015-12-19||+2\d", tail=" "), Word(r"now+3d+12h\h", head=" "))) parsed = parser.parse(r'foo:[2015-12-19||+2\d TO now+3d+12h\h]') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed)
def test_escaping_column(self): # non regression for issue #30 query = r'ip:1000\:\:1000\:\:1/24' tree = SearchField('ip', Word(r'1000\:\:1000\:\:1/24')) parsed = parser.parse(query) self.assertEqual(parsed, tree) self.assertEqual(str(parsed), query) self.assertEqual(parsed.children[0].unescaped_value, "1000::1000::1/24")
def test_auto_name_integration(self): tree = (AndOperation( SearchField("text", Phrase('"foo bar"')), Group(OrOperation( Word("bar"), SearchField("spam", Word("baz")), ), ), )) auto_name(tree) expected = { 'bool': { 'must': [{ 'term': { 'text': { '_name': 'a', 'value': 'foo bar' } } }, { 'bool': { 'should': [{ 'term': { 'text': { '_name': 'c', 'value': 'bar' } } }, { 'match': { 'spam': { '_name': 'd', 'query': 'baz', 'zero_terms_query': 'none' } } }] } }] } } result = self.transformer(tree) self.assertEqual(result, expected)
def test_reserved_ok(self): """Test reserved word do not hurt in certain positions """ tree = SearchField("foo", Word("TO")) parsed = parser.parse('foo:TO') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Word("TO*")) parsed = parser.parse('foo:TO*') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Word("NOT*")) parsed = parser.parse('foo:NOT*') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed) tree = SearchField("foo", Phrase('"TO AND OR"')) parsed = parser.parse('foo:"TO AND OR"') self.assertEqual(str(tree), str(parsed)) self.assertEqual(tree, parsed)
def test_named_queries_exists(self): tree = SearchField("text", Word("*")) set_name(tree.children[0], "a") result = self.transformer(tree) self.assertEqual( result, {"exists": { "field": "text", "_name": "a" }}, )
def test_visit_complex(self): tree = AndOperation( Group( OrOperation(Word("foo"), Word("bar"), Boost(Fuzzy(Word("baz")), force=2))), Proximity(Phrase('"spam ham"')), SearchField("fizz", Regex("/fuzz/")), ) transformed = self.transform(tree) expected = AndOperation( Group( OrOperation( Word("foo@0-0-0"), Word("bar@0-0-1"), Boost(Fuzzy(Word("baz@0-0-2-0-0")), force=2), )), Proximity(Phrase('"spam ham@1-0"')), SearchField("fizz", Regex("/fuzz@2-0/")), ) self.assertEqual(transformed, expected)
def test_named_queries_range(self): tree = SearchField("text", Range(Word("x"), Word("z"))) set_name(tree, "a") result = self.transformer(tree) self.assertEqual( result, {'range': { 'text': { '_name': 'a', 'gte': 'x', 'lte': 'z' } }})
def test_groups(self): tree = (OrOperation( Word('test', tail=" "), Group(AndOperation( SearchField("subject", FieldGroup( OrOperation(Word('foo', tail=" "), Word('bar', head=" "))), tail=" "), Word('baz', head=" ")), head=" "))) parsed = parser.parse('test OR (subject:(foo OR bar) AND baz)') self.assertEqual(str(parsed), str(tree)) self.assertEqual(parsed, tree)
def test_simple_propagation(self): # propagation in nodes with only one children tree = Boost(Group(SearchField("foo", FieldGroup(Plus(Word("bar"))))), force=2) paths_ok, paths_ko = self.propagate_matching(tree, set(), {()}) self.assertEqual(paths_ok, set()) self.assertEqual(paths_ko, {(), (0, ), (0, 0), (0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0, 0)}) paths_ok, paths_ko = self.propagate_matching(tree, {()}, set()) self.assertEqual(paths_ok, {(), (0, ), (0, 0), (0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0, 0)}) self.assertEqual(paths_ko, set())
def test_element_from_path(self): tree = AndOperation( OrOperation( SearchField("bar", Word("test")), Group( AndOperation( Proximity(Phrase('"test"'), 2), SearchField("baz", Word("test")), Fuzzy(Word("test")), Phrase('"test"'), ), ), ), ) names = { "a": (), "b": (0, 1), "c": (0, 1, 0, 2), "d": (0, 1, 0, 2, 0), "e": (0, 1, 0, 3) } self.assertEqual(element_from_path(tree, ()), tree) self.assertEqual(element_from_name(tree, "a", names), tree) self.assertEqual(element_from_path(tree, (0, 1)), tree.children[0].children[1]) self.assertEqual(element_from_name(tree, "b", names), tree.children[0].children[1]) self.assertEqual(element_from_path(tree, (0, 1, 0, 2)), Fuzzy(Word("test"))) self.assertEqual(element_from_name(tree, "c", names), Fuzzy(Word("test"))) self.assertEqual(element_from_path(tree, (0, 1, 0, 2, 0)), Word("test")) self.assertEqual(element_from_name(tree, "d", names), Word("test")) self.assertEqual(element_from_path(tree, (0, 1, 0, 3)), Phrase('"test"')) self.assertEqual(element_from_name(tree, "e", names), Phrase('"test"')) with self.assertRaises(IndexError): element_from_path(tree, (1, ))
def test_check_ok(self): query = (AndOperation( SearchField( "f", FieldGroup( AndOperation( Boost(Proximity(Phrase('"foo bar"'), 4), "4.2"), Prohibit(Range("100", "200"))))), Group(OrOperation(Fuzzy(Word("baz"), ".8"), Plus(Word("fizz")))))) check = LuceneCheck() self.assertTrue(check(query)) self.assertEqual(check.errors(query), []) check = LuceneCheck(zeal=1) self.assertTrue(check(query)) self.assertEqual(check.errors(query), [])
def test_named_queries_object(self): tree = SearchField("book.title", Word("Circus")) set_name(tree, "a") result = self.transformer(tree) # name is repeated on query, but it's not a big deal… self.assertEqual( result, { 'match': { 'book.title': { '_name': 'a', 'query': 'Circus', 'zero_terms_query': 'none' } } })
def test_search_field(self): # FIXME handle space between field name and ':' ? tree = parser.parse("\rfoo:\tbar\n") self.assertEqual(tree, SearchField("foo", Word("bar"))) self.assertEqual(tree.head, "\r") self.assertEqual(tree.tail, "") self.assertEqual(tree.pos, 1) self.assertEqual(tree.size, 9) bar, = tree.children self.assertEqual(bar.head, "\t") self.assertEqual(bar.tail, "\n") self.assertEqual(bar.pos, 6) self.assertEqual(bar.size, 3) self.assertEqual(str(tree), "foo:\tbar\n") self.assertEqual(tree.__str__(head_tail=True), "\rfoo:\tbar\n")