return self.start - span.end

+def bisect_spans(spans, start):

+ if spans[mid].start < start:

class SpanWrappingMatcher(wrappers.WrappingMatcher):

return self.__class__(self.a.copy(), self.b.copy())

+ return 1 + max(self.a.depth(), self.b.depth())

def replace(self, minquality=0):

class SpanNear(SpanQuery):

- """Matches queries that occur near each other. By default, only matches

+ Note: for new code, use :class:`SpanNear2` instead of this class. SpanNear2

+ takes a list of sub-queries instead of requiring you to create a binary

+ Matches queries that occur near each other. By default, only matches

queries that occur right next to each other (slop=1) and in order

# Check the distance between the spans

dist = aspan.distance_to(bspan)

- if~~ dist >=~~ mindist ~~and~~ dist <= slop:

+ if mindist <= dist <= slop:

spans.add(aspan.to(bspan))

+class SpanNear2(SpanQuery):

+ Matches queries that occur near each other. By default, only matches

+ queries that occur right next to each other (slop=1) and in order

+ New code should use this query type instead of :class:`SpanNear`.

+ (Unlike :class:`SpanNear`, this query takes a list of subqueries instead of

+ requiring you to build a binary tree of query objects. This query should

+ also be slightly faster due to less overhead.)

+ For example, to find documents where "whoosh" occurs next to "library"

+ from whoosh import query, spans

+ t1 = query.Term("text", "whoosh")

+ t2 = query.Term("text", "library")

+ q = spans.SpanNear2([t1, t2])

+ To find documents where "whoosh" occurs at most 5 positions before

+ q = spans.SpanNear2([t1, t2], slop=5)

+ To find documents where "whoosh" occurs at most 5 positions before or after

+ q = spans.SpanNear2(t1, t2, slop=5, ordered=False)

+ def __init__(self, qs, slop=1, ordered=True, mindist=1):

+ :param qs: a sequence of sub-queries to match.

+ :param slop: the number of positions within which the queries must

+ occur. Default is 1, meaning the queries must occur right next

+ :param ordered: whether a must occur before b. Default is True.

+ :pram mindist: the minimum distance allowed between the queries.

+ return ("%s(%r, slop=%d, ordered=%s, mindist=%d)"

+ % (self.__class__.__name__, self.qs, self.slop, self.ordered,

+ def __eq__(self, other):

+ return (other and self.__class__ == other.__class__

+ and self.qs == other.qs and self.slop == other.slop

+ and self.ordered == other.ordered

+ and self.mindist == other.mindist)

+ h = hash(self.slop) ^ hash(self.ordered) ^ hash(self.mindist)

+ return self.__class__([fn(q) for q in self.qs], slop=self.slop,

+ ordered=self.ordered, mindist=self.mindist)

+ def matcher(self, searcher, context=None):

+ ms = [q.matcher(searcher, context) for q in self.qs]

+ return self.SpanNear2Matcher(ms, slop=self.slop, ordered=self.ordered,

+ class SpanNear2Matcher(SpanWrappingMatcher):

+ def __init__(self, ms, slop=1, ordered=True, mindist=1):

+ isect = make_binary_tree(binary.IntersectionMatcher, ms)

+ super(SpanNear2.SpanNear2Matcher, self).__init__(isect)

+ return self.__class__([m.copy() for m in self.ms], slop=self.slop,

+ ordered=self.ordered, mindist=self.mindist)

+ def replace(self, minquality=0):

+ if not self.is_active():

+ return mcore.NullMatcher()

+ while i < len(ms) and aspans:

+ # Use a binary search to find the first position we should

+ # start looking for possible matches

+ start = max(0, aspan.start - slop)

+ j = bisect_spans(bspans, start)

+ if (bspan.end < aspan.start - slop

+ or (ordered and aspan.start > bspan.start)):

+ # B is too far in front of A, or B is in front of A

+ # *at all* when ordered is True

+ if bspan.start > aspan.end + slop:

+ # B is too far from A. Since spans are listed in

+ # start position order, we know that all spans after

+ # this one will also be too far.

+ # Check the distance between the spans

+ dist = aspan.distance_to(bspan)

+ if mindist <= dist <= slop:

+ spans.add(aspan.to(bspan))

"""Matches documents that match any of a list of sub-queries. Unlike

query.Or, this class merges together matching spans from the different