Advertisement
Guest User

Untitled

a guest
Oct 22nd, 2016
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.24 KB | None | 0 0
  1. """
  2. Perform query tree:
  3. - got tree with IdxBlockReader at leafs (terms)
  4. - produce matched document ID, one by one
  5. """
  6. import idxblock
  7. import qparser
  8.  
  9.  
  10. class NodePerformer:
  11. def __init__(self, left=None, right=None):
  12. self.left = left
  13. self.right = right
  14.  
  15.  
  16. class TermNodePerformer(NodePerformer):
  17. def __init__(self, node):
  18. NodePerformer.__init__(self)
  19. assert (isinstance(node.idxblock, idxblock.IdxBlockReader))
  20. self.reader = node.idxblock
  21.  
  22. def goto_id(self, id):
  23. return self.reader.goto_id(id)
  24.  
  25. def evaluate(self):
  26. return self.reader.cur_doc()
  27.  
  28.  
  29. class EmptyNodePerformer(NodePerformer):
  30. """
  31. special case for non-existing blocks for terms
  32. """
  33. def __init__(self):
  34. NodePerformer.__init__(self)
  35.  
  36. def goto_id(self, id):
  37. pass
  38.  
  39. def evaluate(self):
  40. return idxblock.OMEGA_ID
  41.  
  42.  
  43. class AndNodePerformer(NodePerformer):
  44. def __init__(self, left, right):
  45. NodePerformer.__init__(self, left, right)
  46.  
  47. def evaluate(self):
  48. lval = self.left.evaluate()
  49. rval = self.right.evaluate()
  50.  
  51. while lval != rval and lval != idxblock.OMEGA_ID and rval != idxblock.OMEGA_ID:
  52. if lval < rval:
  53. self.left.goto_id(rval)
  54. lval = self.left.evaluate()
  55. else:
  56. self.right.goto_id(lval)
  57. rval = self.right.evaluate()
  58.  
  59. if lval == idxblock.OMEGA_ID or rval == idxblock.OMEGA_ID:
  60. return idxblock.OMEGA_ID
  61.  
  62. assert lval == rval
  63. return lval
  64.  
  65. def goto_id(self, id):
  66. self.left.goto_id(id)
  67. self.right.goto_id(id)
  68.  
  69.  
  70. class OrNodePerformer(NodePerformer):
  71. def __init__(self, left, right):
  72. NodePerformer.__init__(self, left, right)
  73.  
  74. def evaluate(self):
  75. lval = self.left.evaluate()
  76. rval = self.right.evaluate()
  77.  
  78. if lval == idxblock.OMEGA_ID:
  79. return rval
  80.  
  81. if rval == idxblock.OMEGA_ID:
  82. return lval
  83.  
  84. return min(lval, rval)
  85.  
  86. def goto_id(self, id):
  87. self.left.goto_id(id)
  88. self.right.goto_id(id)
  89.  
  90.  
  91. class NegationNodePerformer:
  92. """
  93. Negation node - provide numbers which are absent in `operand` node
  94. For example:
  95. - [0, 1, 3] => [2, 4, ...]
  96. - [3] => [0, 1, 2, 4, ...]
  97. - [] => [0, 1, ...]
  98. """
  99. def __init__(self, operand):
  100. self.operand = operand
  101. self.virtual_doc_id = idxblock.ALPHA_ID
  102.  
  103. def evaluate(self):
  104. while self.virtual_doc_id == self.operand.evaluate():
  105. self.virtual_doc_id += 1
  106. self.operand.goto_id(self.virtual_doc_id)
  107.  
  108. return self.virtual_doc_id
  109.  
  110. def goto_id(self, id):
  111. self.operand.goto_id(id)
  112. self.virtual_doc_id = id
  113.  
  114.  
  115. class BadTreeError(Exception):
  116. pass
  117.  
  118.  
  119. class QTreePerformer:
  120. def __init__(self, tree):
  121. assert (isinstance(tree, qparser.QtreeTypeInfo))
  122. self.last_doc_id = idxblock.ALPHA_ID
  123. self.root = QTreePerformer._deep_copy(tree)
  124.  
  125. @staticmethod
  126. def _deep_copy(subroot):
  127. if subroot.is_operator:
  128. if subroot.value == '&':
  129. return AndNodePerformer(QTreePerformer._deep_copy(subroot.left),
  130. QTreePerformer._deep_copy(subroot.right))
  131. if subroot.value == '|':
  132. return OrNodePerformer(QTreePerformer._deep_copy(subroot.left),
  133. QTreePerformer._deep_copy(subroot.right))
  134.  
  135. if subroot.value == '!':
  136. return NegationNodePerformer(QTreePerformer._deep_copy(subroot.unary_operand()))
  137.  
  138. raise BadTreeError('Unknown operator "%s"' % subroot.value)
  139. else:
  140. assert subroot.is_term
  141. return TermNodePerformer(subroot) if subroot.idxblock else EmptyNodePerformer()
  142.  
  143. def finished(self):
  144. return self.last_doc_id == idxblock.OMEGA_ID
  145.  
  146. def next_doc(self):
  147. if self.finished():
  148. return None
  149.  
  150. self.root.goto_id(self.last_doc_id + 1)
  151. self.last_doc_id = self.root.evaluate()
  152.  
  153. if self.finished():
  154. return None
  155.  
  156. return self.last_doc_id
  157.  
  158. def docs(self):
  159. while True:
  160. val = self.next_doc()
  161. if val is None:
  162. break
  163. yield val
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement