Skip to content
This repository was archived by the owner on Nov 21, 2017. It is now read-only.

Commit 3bb7134

Browse files
committed
Issue #7: AndMaybe clause problems with PlusMinus
This removes the generation of AndMaybe clauses by l2cs.PlusMinusPlugin. The plugin's support of '+' is also removed, since CloudSearch has no concept of 'AndMaybe' type clauses. The Plugin is renamed to "MinusPlugin" and cleaned up slightly.
1 parent 54137e0 commit 3bb7134

File tree

2 files changed

+52
-32
lines changed

2 files changed

+52
-32
lines changed

l2cs.py

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import whoosh.qparser
1313
import whoosh.qparser.plugins
1414
import whoosh.qparser.syntax
15+
import whoosh.qparser.taggers
1516
import whoosh.query
1617

1718

@@ -55,10 +56,17 @@ def build_field(clause):
5556
yield clause.text
5657

5758

58-
@handler(whoosh.query.And, whoosh.query.Or, whoosh.query.Not)
59+
@handler(whoosh.query.And, whoosh.query.Or, whoosh.query.Not,
60+
whoosh.query.AndMaybe)
5961
def build_grouper(clause):
6062
yield "("
61-
yield clause.__class__.__name__.lower()
63+
# CloudSearch only supports 'and' and 'or' clauses; neither really fit
64+
# with the concept of "AndMaybe", which tries to "boost" results that
65+
# include the "Maybe" portion of the clause.
66+
if isinstance(clause, whoosh.query.AndMaybe):
67+
yield "and"
68+
else:
69+
yield clause.__class__.__name__.lower()
6270
for child_clause in clause.children():
6371
yield " "
6472
for piece in walk_clause(child_clause):
@@ -154,40 +162,46 @@ def modify_node(self, fieldname, node):
154162
return node
155163

156164

157-
class PlusMinusPlugin(whoosh.qparser.plugins.PlusMinusPlugin):
158-
'''The default PlusMinus plugin doesn't respect the parser's
159-
default grouping, instead blindly using "OR" groupings. This modified
160-
version takes the parser's desired grouping into account
165+
class MinusPlugin(whoosh.qparser.plugins.Plugin):
166+
'''This differs from whoosh's PlusMinusPlugin. The concept of "AndMaybe"
167+
isn't one that applies to CloudSearch, so "+" actions aren't needed.
168+
Additionally, the logic is simplified from the whoosh version to just
169+
swap out the nodes
161170
'''
162-
def do_plusminus(self, parser, group):
171+
class Minus(whoosh.qparser.syntax.MarkerNode):
172+
pass
173+
174+
def __init__(self, minusexpr="-"):
175+
self.minusexpr = minusexpr
176+
177+
def taggers(self, parser):
178+
minus_tagger = whoosh.qparser.taggers.FnTagger(self.minusexpr,
179+
self.Minus,
180+
"minus")
181+
return [(minus_tagger, 0)]
182+
183+
def filters(self, parser):
184+
return [(self.do_minus, 505)]
185+
186+
def do_minus(self, parser, group):
163187
'''This filter sorts nodes in a flat group into "required", "default",
164188
and "banned" subgroups based on the presence of plus and minus nodes.
165189
'''
166-
required = whoosh.qparser.syntax.AndGroup()
167-
banned = whoosh.qparser.syntax.OrGroup()
168-
default = parser.group()
169-
170-
# Which group to put the next node we see into
171-
next_ = default
190+
grouper = group.__class__()
191+
192+
next_not = None
172193
for node in group:
173-
if isinstance(node, self.Plus):
174-
# +: put the next node in the required group
175-
next_ = required
176-
elif isinstance(node, self.Minus):
177-
# -: put the next node in the banned group
178-
next_ = banned
194+
if isinstance(node, self.Minus):
195+
# -: Replace with a NOT node
196+
next_not = whoosh.qparser.syntax.NotGroup()
197+
grouper.append(next_not)
198+
elif next_not is not None:
199+
next_not.append(node)
200+
next_not = None
179201
else:
180-
# Anything else: put it in the appropriate group
181-
next_.append(node)
182-
# Reset to putting things in the optional group by default
183-
next_ = default
184-
185-
group = default
186-
if required:
187-
group = whoosh.qparser.syntax.AndMaybeGroup([required, group])
188-
if banned:
189-
group = whoosh.qparser.syntax.AndNotGroup([group, banned])
190-
return group
202+
grouper.append(node)
203+
204+
return grouper
191205

192206

193207
DEFAULT_PLUGINS = (
@@ -200,7 +214,7 @@ def do_plusminus(self, parser, group):
200214
whoosh.qparser.plugins.OperatorsPlugin(AndMaybe=None,
201215
Require=None),
202216
whoosh.qparser.plugins.EveryPlugin(),
203-
PlusMinusPlugin(),
217+
MinusPlugin(),
204218
)
205219

206220

test_l2cs.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,14 @@ def test_prefix1(self):
7979
def test_alias1(self):
8080
self._run_test("alias1:foo", "(field alias 'foo')")
8181
def test_alias2(self):
82-
'''Make sure the reference the base of the alias still works'''
82+
'''Make sure that referencing the base of the alias still works'''
8383
self._run_test("alias:foo", "(field alias 'foo')")
84+
85+
# Unsupported "+" syntax gets ignored, AndMaybe clauses are avoided
86+
def test_plus1(self):
87+
self._run_test("learn c++ programming", "(and (field text 'learn') (field text 'c++') (field text 'programming'))")
88+
def test_plus2(self):
89+
self._run_test("learn c++", "(and (field text 'learn') (field text 'c++'))")
8490

8591

8692
if __name__ == '__main__':

0 commit comments

Comments
 (0)