Exemplo n.º 1
0
    def get_object(self, request):
        """
        For OPDS 1.1 We should handle a query for search terms
        and criteria provided either as opensearch or 'inline' query.
        OpenSearch defines fields: atom:author, atom:contributor (treated as translator),
        atom:title. Inline query provides author, title, categories (treated as book tags),
        description (treated as content search terms).

        if search terms are provided, we shall search for books
        according to Hint information (from author & contributror & title).

        but if search terms are empty, we should do a different search
        (perhaps for is_book=True)

        """

        query = request.GET.get('q', '')

        inline_criteria = re.findall(self.INLINE_QUERY_RE, query)
        if inline_criteria:
            remains = re.sub(self.INLINE_QUERY_RE, '', query)
            remains = re.sub(r'[ \t]+', ' ', remains)

            def get_criteria(criteria, name):
                for c in criteria:
                    for p in self.MATCHES[name]:
                        if c[p]:
                            if p % 2 == 0:
                                return c[p].replace('+', ' ')
                            return c[p]
                return None

            criteria = dict(map(
                lambda cn: (cn, get_criteria(inline_criteria, cn)),
                ['author', 'translator', 'title', 'categories',
                 'description', 'text']))
            query = remains
            # empty query and text set case?
            log.debug("Inline query = [%s], criteria: %s" % (query, criteria))
        else:
            def remove_dump_data(val):
                """Some clients don't get opds placeholders and just send them."""
                if self.ATOM_PLACEHOLDER.match(val):
                    return ''
                return val

            criteria = dict([(cn, remove_dump_data(request.GET.get(cn, '')))
                        for cn in self.MATCHES.keys()])
            # query is set above.
            log.debug("Inline query = [%s], criteria: %s" % (query, criteria))

        srch = Search()

        book_hit_filter = srch.index.Q(book_id__any=True)
        filters = [book_hit_filter] + [srch.index.Q(
            **{self.PARAMS_TO_FIELDS.get(cn, cn): criteria[cn]}
            ) for cn in self.MATCHES.keys() if cn in criteria
            if criteria[cn]]

        if query:
            q = srch.index.query(
                reduce(operator.or_,
                       [srch.index.Q(**{self.PARAMS_TO_FIELDS.get(cn, cn): query})
                        for cn in self.MATCHES.keys()],
                srch.index.Q()))
        else:
            q = srch.index.query(srch.index.Q())

        q = srch.apply_filters(q, filters).field_limit(score=True, fields=['book_id'])
        results = q.execute()

        book_scores = dict([(r['book_id'], r['score']) for r in results])
        books = Book.objects.filter(id__in=set([r['book_id'] for r in results]))
        books = list(books)
        books.sort(reverse=True, key=lambda book: book_scores[book.id])
        return books
Exemplo n.º 2
0
    def get_object(self, request):
        """
        For OPDS 1.1 We should handle a query for search terms
        and criteria provided either as opensearch or 'inline' query.
        OpenSearch defines fields: atom:author, atom:contributor (treated as translator),
        atom:title. Inline query provides author, title, categories (treated as book tags),
        description (treated as content search terms).

        if search terms are provided, we shall search for books
        according to Hint information (from author & contributror & title).

        but if search terms are empty, we should do a different search
        (perhaps for is_book=True)

        """

        query = request.GET.get('q', '')

        inline_criteria = re.findall(self.INLINE_QUERY_RE, query)
        if inline_criteria:
            remains = re.sub(self.INLINE_QUERY_RE, '', query)
            remains = re.sub(r'[ \t]+', ' ', remains)

            def get_criteria(criteria, name):
                for c in criteria:
                    for p in self.MATCHES[name]:
                        if c[p]:
                            if p % 2 == 0:
                                return c[p].replace('+', ' ')
                            return c[p]
                return None

            criteria = dict(
                map(lambda cn: (cn, get_criteria(inline_criteria, cn)), [
                    'author', 'translator', 'title', 'categories',
                    'description', 'text'
                ]))
            query = remains
            # empty query and text set case?
            log.debug("Inline query = [%s], criteria: %s" % (query, criteria))
        else:

            def remove_dump_data(val):
                """Some clients don't get opds placeholders and just send them."""
                if self.ATOM_PLACEHOLDER.match(val):
                    return ''
                return val

            criteria = dict((cn, remove_dump_data(request.GET.get(cn, '')))
                            for cn in self.MATCHES.keys())
            # query is set above.
            log.debug("Inline query = [%s], criteria: %s" % (query, criteria))

        srch = Search()

        book_hit_filter = srch.index.Q(book_id__any=True)
        filters = [book_hit_filter] + [
            srch.index.Q(**{self.PARAMS_TO_FIELDS.get(cn, cn): criteria[cn]})
            for cn in self.MATCHES.keys() if cn in criteria if criteria[cn]
        ]

        if query:
            q = srch.index.query(
                reduce(operator.or_, [
                    srch.index.Q(**{self.PARAMS_TO_FIELDS.get(cn, cn): query})
                    for cn in self.MATCHES.keys()
                ], srch.index.Q()))
        else:
            q = srch.index.query(srch.index.Q())

        q = srch.apply_filters(q, filters).field_limit(score=True,
                                                       fields=['book_id'])
        results = q.execute()

        book_scores = dict([(r['book_id'], r['score']) for r in results])
        books = Book.objects.filter(id__in=set([r['book_id']
                                                for r in results]))
        books = list(books)
        books.sort(reverse=True, key=lambda book: book_scores[book.id])
        return books