Ejemplo n.º 1
0
def get_search_utility(query=None):
    query = query or {}
    if "pg_catalog" not in app_settings["load_utilities"]:
        return query_utility(ICatalogUtility)
    else:
        found = "SearchableText" in query
        for key in query.keys():
            if key[0] == "_":
                continue
            index = get_index_definition(key)
            if index is None:
                continue
            if index["type"] in ("text", "searchabletext"):
                found = True
                break

        if found:
            return query_utility(ICatalogUtility)
        return query_utility(ICatalogUtility, name="pg_catalog")
Ejemplo n.º 2
0
def get_search_utility(query=None):
    query = query or {}
    if 'pg_catalog' not in app_settings['load_utilities']:
        return query_utility(ICatalogUtility)
    else:
        found = 'SearchableText' in query
        for key in query.keys():
            if key[0] == '_':
                continue
            index = get_index_definition(key)
            if index is None:
                continue
            if index['type'] in ('text', 'searchabletext'):
                found = True
                break

        if found:
            return query_utility(ICatalogUtility)
        return query_utility(ICatalogUtility, name='pg_catalog')
Ejemplo n.º 3
0
    def process_queried_field(
        self, field: str, value
    ) -> typing.Optional[typing.Tuple[typing.Any, typing.List[typing.Any],
                                      typing.List[str]]]:
        # compound field support
        if field.endswith("__or"):
            return self.process_compound_field(field, value, " OR ")
        elif field.endswith("__and"):
            field = field[:-len("__and")]
            return self.process_compound_field(field, value, " AND ")

        result: typing.Any = value
        operator = "="
        if field.endswith("__not"):
            operator = "!="
            field = field[:-len("__not")]
        elif field.endswith("__in"):
            operator = "?|"
            field = field[:-len("__in")]
        elif field.endswith("__eq"):
            operator = "="
            field = field[:-len("__eq")]
        elif field.endswith("__gt"):
            operator = ">"
            field = field[:-len("__gt")]
        elif field.endswith("__lt"):
            operator = "<"
            field = field[:-len("__lt")]
        elif field.endswith("__gte"):
            operator = ">="
            field = field[:-len("__gte")]
        elif field.endswith("__lte"):
            operator = "<="
            field = field[:-len("__lte")]
        elif field.endswith("__starts"):
            operator = "starts"
            field = field[:-len("__starts")]

        index = get_index_definition(field)
        if index is None:
            return None

        _type = index["type"]
        if _type in _type_mapping:
            try:
                result = _type_mapping[_type](value)
            except ValueError:
                # invalid, can't continue... We could throw query parse error?
                return None
        elif _type == "date":
            result = parse(value).replace(tzinfo=None)
        elif _type == "boolean":
            if value in ("true", "True", "yes", "1"):
                result = True
            else:
                result = False
        elif _type == "keyword" and operator not in ("?", "?|"):
            operator = "?"
        elif _type in ("text", "searchabletext"):
            operator = "="
            value = "&".join(to_list(value))
        if _type == "path":
            if operator != "starts":
                # we do not currently support other search types
                logger.warning(f"Unsupported search {field}: {value}")
            operator = "="

        if operator == "?|":
            result = to_list(value)

        if operator == "?" and isinstance(result, list):
            operator = "?|"

        pg_index = get_pg_index(field)
        return pg_index.where(result, operator), [result], pg_index.select()
Ejemplo n.º 4
0
def process_field(field, value):
    if field.endswith("__or"):
        return process_compound_field(field, value, "or")
    elif field.endswith("__and"):
        field = field[:-len("__and")]
        return process_compound_field(field, value, "and")

    modifier = None

    match_type = "must"
    if field.endswith("__should"):
        match_type = "should"
        field = field[:-len("__should")]
    if field.endswith("__not"):
        modifier = "not"
        field = field[:-len("__not")]
    elif field.endswith("__in"):
        modifier = "in"
        field = field[:-len("__in")]
    elif field.endswith("__eq"):
        modifier = "eq"
        field = field[:-len("__eq")]
    elif field.endswith("__gt"):
        modifier = "gt"
        field = field[:-len("__gt")]
    elif field.endswith("__lt"):
        modifier = "lt"
        field = field[:-len("__lt")]
    elif field.endswith("__gte"):
        modifier = "gte"
        field = field[:-len("__gte")]
    elif field.endswith("__lte"):
        modifier = "lte"
        field = field[:-len("__lte")]
    elif field.endswith("__wildcard"):
        modifier = "wildcard"
        field = field[:-len("__wildcard")]

    index = get_index_definition(field)
    if index is None:
        return
    _type = index["type"]
    if not isinstance(value, list):
        value = [value]
        term_keyword = "term"
    else:
        if len(value) > 1:
            term_keyword = "terms"
        else:
            term_keyword = "term"
    result_list = []
    for value_list in value:
        value_cast = None
        if _type == "int":
            try:
                value_cast = int(value_list)
            except ValueError:
                pass
        elif _type == "date":
            value_cast = parse(value_list).timestamp()

        elif _type == "boolean":
            if value_list in ("true", "True", "yes", True):
                value_cast = "true"
            else:
                value_cast = "false"
        if value_cast:
            result_list.append(value_cast)
        else:
            result_list.append(value_list)
    if len(result_list) == 1:
        value = result_list[0]
    else:
        value = result_list

    if modifier is None:
        # Keyword we expect an exact match
        return match_type, {term_keyword: {field: value}}
    elif modifier == "not":
        # Must not be
        return "must_not", {term_keyword: {field: value}}
    elif modifier == "in" and _type in ("text", "searchabletext"):
        # The value list can be inside the field
        return match_type, {"match": {field: value}}
    elif modifier == "eq":
        # The sentence must appear as is it
        value = " ".join(value)
        return match_type, {"match": {field: value}}
    elif modifier in ("gte", "lte", "gt", "lt"):
        return match_type, {"range": {field: {modifier: value}}}
    elif modifier == "wildcard":
        return match_type, {"wildcard": {field: value}}
    else:
        logger.warn("wrong search type: %s modifier: %s field: %s value: %s" %
                    (_type, modifier, field, value))
Ejemplo n.º 5
0
    def process_queried_field(
        self, field: str, value
    ) -> typing.Optional[typing.Tuple[typing.Any, typing.List[typing.Any],
                                      typing.List[str]]]:
        # compound field support
        if field.endswith('__or'):
            return self.process_compound_field(field, value, ' OR ')
        elif field.endswith('__and'):
            field = field[:-len('__and')]
            return self.process_compound_field(field, value, ' AND ')

        result: typing.Any = value

        operator = '='
        if field.endswith('__not'):
            operator = '!='
            field = field[:-len('__not')]
        elif field.endswith('__in'):
            operator = '?|'
            field = field[:-len('__in')]
        elif field.endswith('__eq'):
            operator = '='
            field = field[:-len('__eq')]
        elif field.endswith('__gt'):
            operator = '>'
            field = field[:-len('__gt')]
        elif field.endswith('__lt'):
            operator = '<'
            field = field[:-len('__lt')]
        elif field.endswith('__gte'):
            operator = '>='
            field = field[:-len('__gte')]
        elif field.endswith('__lte'):
            operator = '<='
            field = field[:-len('__lte')]
        elif field.endswith('__starts'):
            operator = 'starts'
            field = field[:-len('__starts')]

        index = get_index_definition(field)
        if index is None:
            return None

        _type = index['type']
        if _type in _type_mapping:
            try:
                result = _type_mapping[_type](value)
            except ValueError:
                # invalid, can't continue... We could throw query parse error?
                return None
        elif _type == 'date':
            result = parse(value).replace(tzinfo=None)
        elif _type == 'boolean':
            if value in ('true', 'True', 'yes', '1'):
                result = True
            else:
                result = False
        elif _type == 'keyword' and operator not in ('?', '?|'):
            operator = '?'
        elif _type in ('text', 'searchabletext'):
            operator = '='
            value = '&'.join(to_list(value))
        if _type == 'path':
            if operator != 'starts':
                # we do not currently support other search types
                logger.warning(f'Unsupported search {field}: {value}')
            operator = '='

        if operator == '?|':
            result = to_list(value)

        if operator == '?' and isinstance(result, list):
            operator = '?|'

        pg_index = get_pg_index(field)
        return pg_index.where(result, operator), [result], pg_index.select()