def _Eval(self, node): if node.getType() is ExpressionParser.FN: func = self._function_table[query_parser.GetQueryNodeText(node)] return func(*node.children) if node.getType() is ExpressionParser.PLUS: return self._EvalBinaryOp(lambda a, b: a + b, 'addition', node) if node.getType() is ExpressionParser.MINUS: return self._EvalBinaryOp(lambda a, b: a - b, 'subtraction', node) if node.getType() is ExpressionParser.DIV: return self._EvalBinaryOp(lambda a, b: a / b, 'division', node) if node.getType() is ExpressionParser.TIMES: return self._EvalBinaryOp(lambda a, b: a * b, 'multiplication', node) if node.getType() is ExpressionParser.NEG: return self._EvalUnaryOp(lambda a: -a, 'negation', node) if node.getType() in (ExpressionParser.INT, ExpressionParser.FLOAT): return float(query_parser.GetQueryNodeText(node)) if node.getType() is ExpressionParser.PHRASE: return query_parser.GetQueryNodeText(node).strip('"') if node.getType() is ExpressionParser.NAME: name = query_parser.GetQueryNodeText(node) if name == '_score': return self._doc.score field = search_util.GetFieldInDocument(self._doc_pb, name) if field: return search_util.GetFieldValue(field) raise _ExpressionError('No field %s in document' % name) raise _ExpressionError('Unable to handle node %s' % node)
def _Snippet(self, query, field, *args): """Create a snippet given a query and the field to query on. Args: query: A query string containing only a bare term (no operators). field: The field name to query on. *args: Unused optional arguments. These are not used on dev_appserver. Returns: A snippet for the field with the query term bolded. """ field = query_parser.GetQueryNodeText(field) terms = self._tokenizer.TokenizeText( query_parser.GetQueryNodeText(query).strip('"')) for term in terms: search_token = tokens.Token(chars=u'%s:%s' % (field, term.chars)) postings = self._inverted_index.GetPostingsForToken(search_token) for posting in postings: if posting.doc_id != self._doc_pb.id( ) or not posting.positions: continue field_val = search_util.GetFieldValue( search_util.GetFieldInDocument(self._doc_pb, field)) if not field_val: continue doc_words = [ token.chars for token in self._case_preserving_tokenizer.TokenizeText(field_val) ] position = posting.positions[0] return self._GenerateSnippet( doc_words, position, search_util.DEFAULT_MAX_SNIPPET_LENGTH) else: field_val = search_util.GetFieldValue( search_util.GetFieldInDocument(self._doc_pb, field)) if not field_val: return None return '%s...' % field_val[:search_util. DEFAULT_MAX_SNIPPET_LENGTH]
def _Eval(self, node): """Evaluate an expression node on the document. Args: node: The expression AST node representing an expression subtree. Returns: The Python value that maps to the value of node. Types are inferred from the expression, so expressions with numeric results will return as python int/long/floats, textual results will be strings, and dates will be datetimes. Raises: _ExpressionError: The expression cannot be evaluated on this document because either the expression is malformed or the document does not contain the required fields. Callers of _Eval should catch _ExpressionErrors and optionally log them; these are not fatal in any way, and are used to indicate that this expression should not be set on this document. """ if node.getType() in self._function_table: func = self._function_table[node.getType()] return func(*node.children) if node.getType() == ExpressionParser.PLUS: return self._EvalBinaryOp(lambda a, b: a + b, 'addition', node) if node.getType() == ExpressionParser.MINUS: return self._EvalBinaryOp(lambda a, b: a - b, 'subtraction', node) if node.getType() == ExpressionParser.DIV: return self._EvalBinaryOp(lambda a, b: a / b, 'division', node) if node.getType() == ExpressionParser.TIMES: return self._EvalBinaryOp(lambda a, b: a * b, 'multiplication', node) if node.getType() == ExpressionParser.NEG: return self._EvalUnaryOp(lambda a: -a, 'negation', node) if node.getType() in (ExpressionParser.INT, ExpressionParser.FLOAT): return float(query_parser.GetQueryNodeText(node)) if node.getType() == ExpressionParser.PHRASE: return query_parser.GetQueryNodeText(node).strip('"') if node.getType() == ExpressionParser.NAME: name = query_parser.GetQueryNodeText(node) if name == '_score': return self._doc.score field = search_util.GetFieldInDocument(self._doc_pb, name) if field: return search_util.GetFieldValue(field) raise _ExpressionError('No field %s in document' % name) raise _ExpressionError('Unable to handle node %s' % node)
def _Snippet(self, query, field, *args): field = query_parser.GetQueryNodeText(field) terms = self._tokenizer.TokenizeText( query_parser.GetQueryNodeText(query).strip('"')) for term in terms: search_token = tokens.Token(chars=u'%s:%s' % (field, term.chars)) postings = self._inverted_index.GetPostingsForToken(search_token) for posting in postings: if posting.doc_id != self._doc_pb.id( ) or not posting.positions: continue field_val = search_util.GetFieldValue( search_util.GetFieldInDocument(self._doc_pb, field)) doc_words = [ token.chars for token in self._case_preserving_tokenizer.TokenizeText(field_val) ] position = posting.positions[0] return self._GenerateSnippet( doc_words, position, search_util.DEFAULT_MAX_SNIPPET_LENGTH)