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
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