def search(self, query=None, sort_by=None, start_offset=0, max_offset=None, fields=None, **kwargs): query = self.parse_query(query) if xapian.Query.empty(query): return 0, lambda: [] database = self.database enquire = xapian.Enquire(database) enquire.set_query(query) if 'collapse_valueno' in self.schema: enquire.set_collapse_key(self.schema['collapse_valueno']) if sort_by: sorter = xapian.MultiValueSorter() for sort_field in sort_by: if sort_field.startswith('-'): reverse = True sort_field = sort_field[1:] # Strip the '-' else: reverse = False # Reverse is inverted in Xapian -- http://trac.xapian.org/ticket/311 sorter.add(self._value_column(sort_field), reverse) enquire.set_sort_by_key(sorter, True) if not max_offset: max_offset = database.get_doccount() - start_offset matches = self._get_enquire_mset(database, enquire, start_offset, max_offset) def result_generator(): for match in matches: r = msgpack.unpackb(self._get_document_data(database, match.document)) if fields is not None: # 如果fields为[], 这情况下,不返回任何一项 item = {} if isinstance(fields, list): for field in fields: if field == 'terms': item['terms'] = dict([(term.term[5:], term.wdf) for term in match.document.termlist() if term.term.startswith('XTEXT')]) else: item[field] = r.get(field) else: item = r yield item return self._get_hit_count(database, enquire), result_generator
def make_enq1(db): enq = xapian.Enquire(db) sorter = xapian.MultiValueSorter() enq.set_sort_by_key(sorter, True) del sorter return enq
def make_enq3(db): enq = xapian.Enquire(db) sorter = xapian.MultiValueSorter() enq.set_sort_by_relevance_then_key(sorter, True) del sorter return enq
def search(self, query, sort_by=None, start_offset=0, end_offset=None, fields='', highlight=False, facets=None, date_facets=None, query_facets=None, narrow_queries=None, spelling_query=None, limit_to_registered_models=True, result_class=None, **kwargs): """ Executes the Xapian::query as defined in `query`. Required arguments: `query` -- Search query to execute Optional arguments: `sort_by` -- Sort results by specified field (default = None) `start_offset` -- Slice results from `start_offset` (default = 0) `end_offset` -- Slice results at `end_offset` (default = None), if None, then all documents `fields` -- Filter results on `fields` (default = '') `highlight` -- Highlight terms in results (default = False) `facets` -- Facet results on fields (default = None) `date_facets` -- Facet results on date ranges (default = None) `query_facets` -- Facet results on queries (default = None) `narrow_queries` -- Narrow queries (default = None) `spelling_query` -- An optional query to execute spelling suggestion on `limit_to_registered_models` -- Limit returned results to models registered in the current `SearchSite` (default = True) Returns: A dictionary with the following keys: `results` -- A list of `SearchResult` `hits` -- The total available results `facets` - A dictionary of facets with the following keys: `fields` -- A list of field facets `dates` -- A list of date facets `queries` -- A list of query facets If faceting was not used, the `facets` key will not be present If `query` is None, returns no results. If `INCLUDE_SPELLING` was enabled in the connection options, the extra flag `FLAG_SPELLING_CORRECTION` will be passed to the query parser and any suggestions for spell correction will be returned as well as the results. """ if xapian.Query.empty(query): return { 'results': [], 'hits': 0, } database = self._database() if result_class is None: result_class = SearchResult if self.include_spelling is True: spelling_suggestion = self._do_spelling_suggestion( database, query, spelling_query) else: spelling_suggestion = '' if narrow_queries is not None: query = xapian.Query( xapian.Query.OP_AND, query, xapian.Query(xapian.Query.OP_AND, [ self.parse_query(narrow_query) for narrow_query in narrow_queries ])) if limit_to_registered_models: registered_models = self.build_models_list() if len(registered_models) > 0: query = xapian.Query( xapian.Query.OP_AND, query, xapian.Query(xapian.Query.OP_OR, [ xapian.Query('%s%s' % (DOCUMENT_CT_TERM_PREFIX, model)) for model in registered_models ])) enquire = xapian.Enquire(database) if hasattr(settings, 'HAYSTACK_XAPIAN_WEIGHTING_SCHEME'): enquire.set_weighting_scheme( xapian.BM25Weight(*settings.HAYSTACK_XAPIAN_WEIGHTING_SCHEME)) enquire.set_query(query) if sort_by: sorter = xapian.MultiValueSorter() for sort_field in sort_by: if sort_field.startswith('-'): reverse = True sort_field = sort_field[1:] # Strip the '-' else: reverse = False # Reverse is inverted in Xapian -- http://trac.xapian.org/ticket/311 sorter.add(self._value_column(sort_field), reverse) enquire.set_sort_by_key_then_relevance(sorter, True) results = [] facets_dict = { 'fields': {}, 'dates': {}, 'queries': {}, } if not end_offset: end_offset = database.get_doccount() - start_offset matches = self._get_enquire_mset(database, enquire, start_offset, end_offset) for match in matches: app_label, module_name, pk, model_data = pickle.loads( self._get_document_data(database, match.document)) if highlight: model_data['highlighted'] = { self.content_field_name: self._do_highlight(model_data.get(self.content_field_name), query) } results.append( result_class(app_label, module_name, pk, match.percent, **model_data)) if facets: facets_dict['fields'] = self._do_field_facets(results, facets) if date_facets: facets_dict['dates'] = self._do_date_facets(results, date_facets) if query_facets: facets_dict['queries'] = self._do_query_facets( results, query_facets) return { 'results': results, 'hits': self._get_hit_count(database, enquire), 'facets': facets_dict, 'spelling_suggestion': spelling_suggestion, }