示例#1
0
def _build_exists_query(field, value):
    """Builds an exists query."""
    real_field = field[:field.rindex('_')]

    kind = 'must' if value else 'must_not'
    query = {
        kind: Exists(field=real_field),
    }
    return Bool(**query)
示例#2
0
    def get_query_condition(self, url_parameter, field, value):
        """
        Return an ElasticSearch DSL query object with the appropriate settings
        for its kind and values from the given url_parameter.
        :param url_parameter: String of the URL parameter for this query.
        :param field: String of the ElasticSearch document field to search.
        :param value: Raw value to look for in this query.
        :returns: Some kind of Query child class.
        """
        settings = self.query_parameters.get(url_parameter)
        if not settings:
            raise KeyError("Parameter %s has no query parameters defined." %
                           url_parameter)

        # The resultant query_class_parameters dictionary looks something like:
        # {
        #   'query_key': 'value',
        #   'fields': ['foo', 'bar', 'baz'],
        # }
        # Attributes is the leftover **kwargs from the original function call.
        # query_class_parameters = {**{settings.get('query_key'): value}, **settings.get('attributes')}

        if settings.get('query_class') is Wildcard:
            search_value = "*%s*" % value
            return Wildcard(**{field: {'value': search_value}})
        elif settings.get('query_class') is MatchPhrase:
            return MatchPhrase(**{field: value})
        elif settings.get('query_class') is Prefix:
            # If you're having problems with Prefix queries, see if the
            # whitespace analyzer is set! See the RecipeIndex class for more.
            return Prefix(**{field: {'value': value}})
        elif settings.get('query_class') is Match:
            return Match(**{field: {'query': value}})
        elif settings.get('query_class') is Exists:
            return Exists(**{'field': field})
        elif settings.get('query_class') is Range:
            # This is some hacks to simplify URL queries. This may be a bad idea.
            # Range() queries do not support 'eq' (use Match() for that). To cheat
            # this in my interface if something sets this a key of 'eq' then we
            # under the hood convert this to a Match query.
            if 'eq' in value.keys():
                return Match(**{field: {'query': value.get('eq')}})
            return Range(**{field: value})
        else:
            raise KeyError("Unsupported query class")
    def translate_clause(self, clause, field):
        if ("constraint" in clause):
            match_params = {}
            query_type = clause.get("query_type", "match")
            match_field_params = {}
            match_field_params["query"] = clause["constraint"]
            #match_field_params["type"] = query_type
            match_field_params["boost"] = field.get("weight", 1.0)
            match_field_params["_name"] = "{}:{}:{}".format(
                clause.get("_id"), field.get("name"), clause.get("constraint"))
            match_params[field["name"]] = match_field_params
            if query_type == "match_phrase":
                match_params_mp = {}
                match_field_params_mp = copy.copy(match_field_params)
                match_field_params_mp[
                    "boost"] = match_field_params_mp["boost"] * len(
                        clause.get("constraint").split(" "))
                match_field_params_mp[
                    "_name"] = match_field_params_mp["_name"] + ":match_phrase"
                match_params_mp[field["name"]] = match_field_params_mp
                match_field_params_mp["slop"] = 10
                mp = MatchPhrase(**match_params_mp)
                m = Match(**match_params)
                return Bool(must=[m], should=[mp])
            else:
                if "date" in clause.get("type", "owl:Thing").lower():
                    match_field_params.pop("query", None)
                    if re.match("\d\d\d\d-\d\d-\d\d", clause["constraint"]):
                        match_field_params["gte"] = clause["constraint"]
                    else:
                        match_field_params["gte"] = "{}||/d".format(
                            clause["constraint"])
                    match_field_params["lt"] = "{}||+1d/d".format(
                        clause["constraint"])
                    return Range(**match_params)

                elif clause.get("type", "owl:Thing") == "owl:Thing":
                    match_field_params["boost"] = field.get("weight", 1.0) * 2
                return Match(**match_params)
        else:
            return Exists(field=field["name"])
         ]),
     ]),
 ),
 (
     "municipalities",
     "gt|population|42108",
     Bool(should=[
         Range(population={"gt": 42108}),
         Range(population__value__total={"gt": 42108}),
     ]),
 ),
 (
     "places",
     "exists|state",
     Bool(should=[
         Exists(field="state"),
         Exists(field="v_municipality.state")
     ]),
 ),
 (
     "places",
     "exists||or|state|name",
     Bool(should=[
         Exists(field="state"),
         Exists(field="name"),
         Exists(field="v_municipality.state"),
     ]),
 ),
 (
     "places",
     "exists||and|state|name",
示例#5
0
    def get_query_conditions(self, url_parameter, fields, value):
        """
        Return a list of ElasticSearch DSL query objects with the appropriate settings
        for its kind and values from the given url_parameter.
        :param url_parameter: String of the URL parameter for this query.
        :param fields: List[String] of the ElasticSearch document fields to search.
        :param value: Raw value to look for in this query.
        :returns: Some kind of Query child class.
        """
        settings = self.query_parameters.get(url_parameter)
        if not settings:
            raise KeyError("Parameter %s has no query parameters defined." %
                           url_parameter)

        # The resultant query_class_parameters dictionary looks something like:
        # {
        #   'query_key': 'value',
        #   'fields': ['foo', 'bar', 'baz'],
        # }
        # Attributes is the leftover **kwargs from the original function call.
        # query_class_parameters = {**{settings.get('query_key'): value}, **settings.get('attributes')}

        conditions = []

        # QueryClasses that take all fields at once get constructed here.
        # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html
        if settings.get('query_class') is MultiMatch:
            conditions.append(MultiMatch(**{'query': value, 'fields': fields}))
            return conditions

        # For the rest, cycle through each field and build an object for each of them.
        for field in fields:
            if settings.get('query_class') is Wildcard:
                search_value = "*%s*" % value
                conditions.append(Wildcard(**{field: {'value': search_value}}))
            elif settings.get('query_class') is MatchPhrase:
                conditions.append(MatchPhrase(**{field: value}))
            elif settings.get('query_class') is Prefix:
                # If you're having problems with Prefix queries, see if the
                # whitespace analyzer is set! See the RecipeIndex class for more.
                conditions.append(Prefix(**{field: {'value': value}}))
            elif settings.get('query_class') is Match:
                conditions.append(Match(**{field: {'query': value}}))
            elif settings.get('query_class') is Exists:
                conditions.append(Exists(**{'field': field}))
            elif settings.get('query_class') is Range:
                # This is some hacks to simplify URL queries. This may be a bad idea.
                # Range() queries do not support 'eq' (use Match() for that). To cheat
                # this in my interface if something sets this a key of 'eq' then we
                # under the hood convert this to a Match query.
                if 'eq' in value.keys():
                    conditions.append(
                        Match(**{field: {
                            'query': value.get('eq')
                        }}))
                else:
                    conditions.append(Range(**{field: value}))
            # Since MultiMatch takes all fields at once, it is constructed outside of this area.
            else:
                raise KeyError("Unsupported query class")

        # Return the list
        return conditions