Esempio n. 1
0
 def filter_tags(self, tag_ids):
     """
         Method to filter or negate videos by tag(s)
     """
     filters = []
     tags, negated_tags = process_comma_seperate_filters(tag_ids)
     if negated_tags:
         filters.append(~Q(tag_ids=negated_tags))
     if tags:
         filters.append(Q(tag_ids=tags))
     return self.filter(*filters)
Esempio n. 2
0
    def test_add_q_or(self):
        """Test that two Q objects can be added to a query without needing to wrap them in
        another Q object
        """
        query = Query(FakeDocument)

        q_1 = Q(foo=42)
        q_2 = Q(foo=128)

        query.add_q(q_1)
        query.add_q(q_2, conn=Q.OR)

        self.assertEqual(u'((foo:"42") OR (foo:"128"))', unicode(query))
Esempio n. 3
0
    def filter_private_to_project_ids(
            self, project_ids=None, allow_public=True):
        """
            Filters private videos by the project they are private to.

            Also returns public videos by default
        """
        q = Q()
        if allow_public:
            q = Q(
                private_to_project_ids='___NONE___')

        if project_ids:  # thor falls over if an empty list is passed
            q = q | Q(private_to_project_ids=project_ids)

        return self.filter(q)
Esempio n. 4
0
    def test_clone_filters(self):
        q = SearchQuery(
            "dummy",
            document_class=FakeDocument).filter((Q(foo="bar") | Q(foo="baz"))
                                                & ~Q(foo="neg"))

        q1 = q.filter(~Q(foo="neg2"))

        self.assertEqual(u'(((foo:"bar") OR (foo:"baz")) AND NOT (foo:"neg"))',
                         unicode(q.query))

        self.assertEqual(
            u'('
            '(((foo:"bar") OR (foo:"baz")) AND NOT (foo:"neg")) '
            'AND NOT (foo:"neg2")'
            ')', unicode(q1.query))
Esempio n. 5
0
    def test_before(self):
        query = Query(FakeDocument)

        today = datetime.date.today()
        query.add_q(Q(bar__lt=today))

        self.assertEqual(u"(bar < {0})".format(today.isoformat()),
                         unicode(query))
Esempio n. 6
0
    def test_after(self):
        query = Query(FakeDocument)

        today = datetime.date.today()
        query.add_q(Q(bar__gt=today))

        self.assertEqual(
            u"(bar > {0} AND NOT bar:{1})".format(today.isoformat(),
                                                  DateField().none_value()),
            unicode(query))
Esempio n. 7
0
    def search_tags(self, request):
        """
            API Endpoint to search global tags.

            Object disposed after request is completed.
        """
        results_limit = 10
        project_search_results = []
        global_search_results = []

        i = Index(name='tags')
        search_query = i.search(AutoCompleteTagDocument)

        if request.q:
            search_query = search_query.filter(n_grams=request.q)

        if request.project_id:
            search_query = search_query.filter(project_ids=request.project_id)

            project_search_results = list(search_query[:results_limit])

            # get 5 global results or more if we don't have enough project
            # results
            if len(project_search_results) < (results_limit / 2):
                remaining = results_limit - len(project_search_results)
            else:
                remaining = results_limit / 2

            # hack - need to get the search package to clone queries
            # shouldn't need to build up an entirely new object
            search_query = i.search(AutoCompleteTagDocument).filter(
                ~Q(project_ids=request.project_id))

            if request.q:
                search_query = search_query.filter(n_grams=request.q)

            # get global results
            global_search_results = list(search_query[:remaining])
        else:
            global_search_results = search_query[:results_limit]

        return TagSplitListResponse(
            project_tags=[
                self.tag_document_mapper.map(
                    tag, project_id=request.project_id)
                for tag in project_search_results
            ],
            global_tags=[
                self.tag_document_mapper.map(tag)
                for tag in global_search_results
            ])
Esempio n. 8
0
    def multi_filter(self, filters):
        """
            Takes an object of filter arguments and applies the
            individual filters
        """

        # all filters should clone the query object
        video_search = self

        # filter on project
        if filters.project_id:
            video_search = video_search.filter_projects(filters.project_id)

        # filter on keywords
        if filters.q:
            video_search = video_search.keywords(filters.q)

        # geosearch
        if filters.location:
            video_search = video_search.geo_search(filters.location)

        # apply channel filter
        if filters.channel_ids:
            video_search = video_search.filter_channels(filters.channel_ids)

        # apply collection filter
        if getattr(filters, 'collection_id', None):
            video_search = video_search.filter_collections(
                filters.collection_id)

        # apply tags - negated and regular
        if filters.tag_ids:
            video_search = video_search.filter_tags(filters.tag_ids)

        # apply date filtering
        if filters.date:
            video_search = video_search.filter_date(filters.date)

        if getattr(filters, 'youtube_id', None):
            video_search = video_search.filter_youtube_id(filters.youtube_id)

        if getattr(filters, 'exclude_ids', None):
            ids = filters.exclude_ids.split(',')
            if ids:
                video_search = video_search.filter(~Q(id=ids))

        return video_search
Esempio n. 9
0
    def search_videos(self, request):
        """
            API Endpoint to quick search videos. A project ID can be passed
            in order to restrict the search to project context. Default
            is to search all videos within a users assigned projects plus
            any other videos in Montage that are assigned to public projects.
        """
        user_projects = self.get_user_project_ids()

        if request.project_id and request.project_id not in user_projects:
            raise NotFoundException

        # now search for all videos matching the query
        video_search = (VideoSearch.create('videos',
                                           VideoDocument,
                                           ids_only=False))

        if request.q:
            video_search = video_search.keywords(request.q)

        if request.exclude_ids:
            ids = request.exclude_ids.split(',')
            if ids:
                video_search = video_search.filter(~Q(id=ids))

        # if we are constraining to a project then do that.
        # otherwise, we want to search for videos in projects that the user has
        # access to
        if request.project_id:
            video_search = video_search.filter(project_id=request.project_id)
        else:
            video_search = video_search.filter_private_to_project_ids(
                user_projects)

        return OneSearchVideoListResponse(items=map(
            self.video_index_mapper.map, video_search[:1000]),
                                          is_list=True)
Esempio n. 10
0
 def test_geosearch_gte(self):
     query = Query(FakeGeoDocument)
     query.add_q(Q(my_loc__geo_gte=GeoQueryArguments(3.14, 6.28, 20)))
     self.assertEqual(
         u"(distance(my_loc, geopoint(3.140000, 6.280000)) >= 20)",
         unicode(query))
Esempio n. 11
0
    def test_basic_keywords(self):
        query = Query(FakeDocument)
        query.add_q(Q(foo__gt=42))

        self.assertEqual(u"(foo > 42)", unicode(query))
Esempio n. 12
0
    def filter_date(self, date_string):
        """
            Method to filter videos by a date string

            date_string is a string formatted in any of the following ways:

            - `{field_name}__{operation}` - where operation is `true` or `false`
            - `{field_name}__{operation}__{date}` - where operation is `after`, `exact` or `before`
            - `{field_name}__{operation}__{from_date}__{to_date}` - where operation is `between` or `notbetween`

            Where:

            - `field_name`: either `published` or `recorded`
            - `operation`: one of:
                - `true`: all videos with this date defined.
                - `false`: all videos without this date defined
                - `after`: all videos where this date is greater than `date`
                - `before`: all videos where this date is less than `date`
                - `exact`: all videos where this date is equal to `date`
                - `between`: all videos where this date is greater than `from_date` and less than `to_date`
                - `notbetween`: all videos where this date is less than `from_date` and greater than `to_date`
        """
        parts = date_string.split('__')
        field_name = parts[0]

        if parts[1] == 'true':
            return self.filter(~Q(**{field_name: datetime.date.max}))

        if parts[1] == 'false':
            return self.filter(**{field_name: datetime.date.max})

        if not len(parts) > 2:
            raise BadSearchDateFormatException(
                "Value must be formatted {op}__{date} or "
                "between__{from_date}__{to_date}")

        op = parts[1]
        date = datetime.datetime.strptime(parts[2], '%Y-%m-%d')

        if op == "after":
            return self.filter(**{"{0}__gte".format(field_name): date})

        elif op == "exact":
            return self.filter(**{field_name: date})

        elif op == "before":
            return self.filter(**{"{0}__lte".format(field_name): date})

        elif op in ("between", "notbetween",):
            if not len(parts) == 4:
                raise BadSearchDateFormatException(
                    "Between dates operation requires two "
                    "double-underscore delimited dates")
            to_date = datetime.datetime.strptime(parts[3], '%Y-%m-%d')

            if op == "notbetween":
                return self.filter(
                    Q(**{"{0}__lte".format(field_name): date}) |
                    Q(**{"{0}__gte".format(field_name): to_date})
                )
            else:
                return self.filter(**{
                    "{0}__gte".format(field_name): date,
                    "{0}__lte".format(field_name): to_date
                })
        else:
            raise BadSearchDateFormatException(
                "{0} is not a supported operation".format(op))