Example #1
0
    def get_default_filters(self, request):
        fields = super(InitiativeSearchFilter, self).get_filter_fields(request)

        permission = 'initiatives.api_read_initiative'

        if not request.user.has_perm(permission):
            filters = [Term(owner_id=request.user.id)]

            if 'owner.id' not in fields:
                filters.append(Term(status='approved'))

            return filters
        elif 'owner.id' in fields and request.user.is_authenticated:
            value = request.user.pk
            return [
                Nested(path='owner', query=Term(owner__id=value))
                | Nested(path='promoter', query=Term(promoter__id=value))
                | Nested(path='activity_manager',
                         query=Term(activity_manager__id=value))
                | Nested(path='activity_owners',
                         query=Term(activity_owners__id=value))
                | Term(status='approved')
            ]
        else:
            return [Term(status='approved')]
Example #2
0
    def get_filter(self, request, field):
        # Also return activity_manger.id when filtering on owner.id
        if field == 'owner.id':
            value = request.GET['filter[{}]'.format(field)]
            return Q(
                Nested(path='owner', query=Term(**{field: value}))
                | Nested(path='promoter', query=Term(promoter__id=value))
                | Nested(path='activity_owners',
                         query=Term(activity_owners__id=value))
                | Nested(path='activity_manager',
                         query=Term(activity_manager__id=value)))

        return super(InitiativeSearchFilter, self).get_filter(request, field)
Example #3
0
    def _get_nested_query(self, *, query, path, fields):
        """Generate a nested query with passed parameters."""
        queries = self._get_queries(
            query=query,
            fields=fields,
        )

        raw_fields = [
            # Remove boosting from the field
            re.sub(r'\^.*$', '', field) for field in fields
        ]

        # Highlight from the raw fields too, if it is a single term.
        if self._is_single_term(query):
            raw_fields.extend(
                [re.sub(r'\^.*$', '.raw', field) for field in fields])

        highlight = dict(
            self._highlight_options,
            fields={field: {}
                    for field in raw_fields},
        )

        return Nested(
            path=path,
            inner_hits={'highlight': highlight},
            query=Bool(should=queries),
        )
Example #4
0
    def _get_nested_query(self, *, query, path, fields):
        """Generate a nested query with passed parameters."""
        queries = self._get_queries(
            query=query,
            fields=fields,
        )

        raw_fields = [
            # Remove boosting from the field
            re.sub(r'\^.*$', '', field)
            for field in fields
        ]

        highlight = dict(
            self._highlight_options,
            fields={
                field: {}
                for field in raw_fields
            },
        )

        return Nested(
            path=path,
            inner_hits={'highlight': highlight},
            query=Bool(should=queries),
        )
def keywords_query(query, lang):
    return Nested(
        path='keywords',
        query=Bool(
            must=[Term(keywords__name=query),
                  Term(keywords__language=lang)]),
    )
Example #6
0
    def get_filter(self, request, field):
        value = request.GET['filter[{}]'.format(field)]

        if '.' in field:
            path = field.split('.')[0]
            return Nested(path=path, query=Term(**{field: value}))

        else:
            try:
                return getattr(self, 'get_{}_filter'.format(field))(value, request)
            except AttributeError:
                return Term(**{field: value})
Example #7
0
 def get_default_filters(self, request):
     permission = 'activities.api_read_activity'
     if not request.user.has_perm(permission):
         return [
             Nested(
                 path='owner',
                 query=Term(owner__id=request.user.pk)
             ),
             ~Terms(status=['draft', 'needs_work', 'submitted', 'deleted', 'closed', 'cancelled'])
         ]
     else:
         return [
             ~Terms(status=['draft', 'needs_work', 'submitted', 'deleted', 'closed', 'cancelled'])
         ]
Example #8
0
    def generate_nested_query(self, query, path, fields, inner_hits):
        """Generate a nested query with passed parameters."""
        queries = []

        for operator in self.operators:
            query_string = SimpleQueryString(query=query,
                                             fields=fields,
                                             default_operator=operator)
            queries.append(query_string)

        bool_query = Bool(should=queries)

        nested_query = Nested(path=path,
                              inner_hits=inner_hits,
                              query=bool_query)
        return nested_query
Example #9
0
    def get_filters(self, request):
        filters = super(ActivitySearchFilter, self).get_filters(request)
        regex = re.compile('^filter\[segment\.(?P<type>[\w\-]+)\]$')
        for key, value in list(request.GET.items()):
            matches = regex.match(key)
            if matches:
                filters.append(
                    Nested(
                        path='segments',
                        query=Term(
                            segments__type=matches.groupdict()['type']
                        ) & Term(
                            segments__id=value
                        )
                    )
                )

        return filters
Example #10
0
    def get_search_query(self, request):
        terms = request.GET.get(self.search_field)

        if terms:
            queries = []
            for field in self.search_fields:
                boost = self.boost.get(field, 1)
                if '.' in field:
                    path = field.split('.')[0]
                    query = Nested(
                        path=path,
                        query=MatchPhrasePrefix(
                            **{field: {'query': terms, 'boost': boost}}
                        )
                    )
                else:
                    query = MatchPhrasePrefix(**{field: {'query': terms, 'boost': boost}})

                queries.append(query)

            return Bool(should=queries)
Example #11
0
    def _get_nested_query(self, *, query, path, fields):
        """Generate a nested query with passed parameters."""
        queries = self._get_queries(
            query=query,
            fields=fields,
        )
        bool_query = Bool(should=queries)

        raw_fields = [
            # Remove boosting from the field
            re.sub(r'\^.*$', '', field) for field in fields
        ]

        # The ``post_filter`` filter will only filter documents
        # at the parent level (domains is a nested document),
        # resulting in results with domains that don't match the current
        # role_name being filtered, so we need to force filtering by role_name
        # on the ``domains`` document here. See #8268.
        # TODO: We should use a flattened document instead
        # to avoid this kind of problems and have faster queries.
        role_name = self.filter_values.get('role_name')
        if path == 'domains' and role_name:
            role_name_query = Bool(must=Terms(
                **{'domains.role_name': role_name}))
            bool_query = Bool(must=[role_name_query, bool_query])

        highlight = dict(
            self._highlight_options,
            fields={field: {}
                    for field in raw_fields},
        )

        return Nested(
            path=path,
            inner_hits={'highlight': highlight},
            query=bool_query,
        )
Example #12
0
    def aggregate(self, request, queryset, view):
        filter_query_params = self.get_filter_query_params(request,
                                                           view).values()
        __facets = self.construct_facets(request, view)
        __nested_facets = self.construct_nested_facets(request, view)
        __facets.update(__nested_facets)
        for __field, __facet in __facets.items():
            agg = __facet["facet"].get_aggregation()
            agg_filter = Q("match_all")
            global_facet = __facet.get("global", False)
            nested_facet = "path" in __facet
            for options in filter_query_params:
                if nested_facet:
                    if __facet["filter_field"] == options["field"] or __facet[
                            "filter_field"] == options.get(
                                "filter_field"
                            ):  # Don't filter nested aggregation on its own field
                        continue
                else:
                    if __field == options["field"] or __field == options.get(
                            "filter_field"
                    ):  # Don't filter aggregation on its own field
                        continue

                if (isinstance(options["values"], (list, tuple))
                        and options["lookup"] is None):
                    if "path" in options:  # Filter term is nested
                        if options["path"] == "keywords":
                            for val in options["values"]:
                                agg_filter &= Nested(
                                    path=options["path"],
                                    query=MatchPhrase(
                                        **{options["field"]: val}),
                                )
                        else:
                            agg_filter &= Nested(
                                path=options["path"],
                                query=Terms(
                                    **{options["field"]: options["values"]}),
                            )
                    else:
                        agg_filter &= Q(
                            "terms", **{options["field"]: options["values"]})
                    continue

                lookup_filter = Q("match_all")
                for value in options["values"]:
                    if options["lookup"] == LOOKUP_FILTER_TERMS:
                        lookup_filter &= Q(
                            "terms",
                            **{
                                options["field"]:
                                self.split_lookup_complex_value(value)
                            },
                        )
                    elif options["lookup"] == LOOKUP_FILTER_RANGE:
                        lookup_filter &= Q(
                            "range",
                            **{options["field"]: self.get_range_params(value)})
                    elif options["lookup"] == LOOKUP_QUERY_GT:
                        lookup_filter &= Q(
                            "range",
                            **{
                                options["field"]:
                                self.get_gte_lte_params(value, "gt")
                            },
                        )
                    elif options["lookup"] == LOOKUP_QUERY_GTE:
                        lookup_filter &= Q(
                            "range",
                            **{
                                options["field"]:
                                self.get_gte_lte_params(value, "gte")
                            },
                        )
                    elif options["lookup"] == LOOKUP_QUERY_LT:
                        lookup_filter &= Q(
                            "range",
                            **{
                                options["field"]:
                                self.get_gte_lte_params(value, "lt")
                            },
                        )
                    elif options["lookup"] == LOOKUP_QUERY_LTE:
                        lookup_filter &= Q(
                            "range",
                            **{
                                options["field"]:
                                self.get_gte_lte_params(value, "lte")
                            },
                        )
                    elif options["lookup"] == "match_phrase":
                        lookup_filter &= MatchPhrase(
                            **{options["field"]: value})

                if "path" in options:  # Filter term is nested
                    agg_filter &= Nested(path=options["path"],
                                         query=lookup_filter)
                else:
                    agg_filter &= lookup_filter

            if nested_facet:
                if global_facet:
                    queryset.aggs.bucket(
                        "_filter_" + __field, "global"
                    ).bucket(
                        # Filter must appear BEFORE nested aggregation to have effect
                        "_filter_" + __field,
                        "filter",
                        filter=agg_filter,
                    ).bucket("_filter_" + __field,
                             "nested",
                             path=__facet["path"]).bucket(__field, agg)
                else:
                    queryset.aggs.bucket("_filter_" + __field,
                                         "filter",
                                         filter=agg_filter).bucket(
                                             "_filter_" + __field,
                                             "nested",
                                             path=__facet["path"]).bucket(
                                                 __field, agg)
            else:
                if global_facet:
                    queryset.aggs.bucket("_filter_" + __field,
                                         "global").bucket(
                                             "_filter_" + __field,
                                             "filter",
                                             filter=agg_filter).bucket(
                                                 __field, agg)
                else:
                    queryset.aggs.bucket("_filter_" + __field,
                                         "filter",
                                         filter=agg_filter).bucket(
                                             __field, agg)

        return queryset
Example #13
0
    def get_sort_popularity(self, request):
        score = FunctionScore(
            score_mode='sum',
            functions=[
                SF(
                    'field_value_factor',
                    field='status_score',
                    weight=10,
                    factor=10
                ),
                SF(
                    'gauss',
                    weight=0.1,
                    created={
                        'scale': "365d"
                    },
                ),
            ]
        ) | FunctionScore(
            score_mode='multiply',
            functions=[
                SF(
                    'field_value_factor',
                    field='contribution_count',
                    missing=0
                ),
                SF(
                    'gauss',
                    weight=0.1,
                    multi_value_mode='avg',
                    contributions={
                        'scale': '5d'
                    },
                ),
            ]
        )

        if request.user.is_authenticated:
            if request.user.skills:
                score = score | FunctionScore(
                    score_mode='first',
                    functions=[
                        SF({
                            'filter': Nested(
                                path='expertise',
                                query=Q(
                                    'terms',
                                    expertise__id=[skill.pk for skill in request.user.skills.all()]
                                )
                            ),
                            'weight': 1,
                        }),
                        SF({'weight': 0}),
                    ]
                )

            if request.user.favourite_themes:
                score = score | FunctionScore(
                    score_mode='first',
                    functions=[
                        SF({
                            'filter': Nested(
                                path='theme',
                                query=Q(
                                    'terms',
                                    theme__id=[theme.pk for theme in request.user.favourite_themes.all()]
                                )
                            ),
                            'weight': 1,
                        }),
                        SF({'weight': 0}),
                    ]
                )

            position = None
            if request.user.location and request.user.location.position:
                position = {
                    'lat': request.user.location.position.latitude,
                    'lon': request.user.location.position.longitude
                }
            elif request.user.place and request.user.place.position:
                position = {
                    'lat': request.user.place.position.latitude,
                    'lon': request.user.place.position.longitude
                }

            if position:
                score = score | FunctionScore(
                    score_mode='first',
                    functions=[
                        SF({
                            'filter': {'exists': {'field': 'position'}},
                            'weight': 1,
                            'gauss': {
                                'position': {
                                    'origin': position,
                                    'scale': "100km"
                                },
                                'multi_value_mode': 'max',
                            },
                        }),
                        SF({'weight': 0}),
                    ]
                )

        return score