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)
Beispiel #2
0
    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]
Beispiel #3
0
    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)