+import haystack.backends.solr_backend
+from haystack.query import SearchQuerySet
+from haystack.constants import ID, DJANGO_CT, DJANGO_ID
+from haystack.utils import get_identifier
+
+
+from django.conf import settings
+
+
+class MoreLikeThisSearchQuerySet(SearchQuerySet):
+ def more_like_this(self, model_instance, **kwargs):
+ clone = self._clone()
+ clone.query.more_like_this(model_instance, **kwargs)
+ return clone
+
+
+class CustomSolrSearchQuery(haystack.backends.solr_backend.SolrSearchQuery):
+ def more_like_this(self, model_instance, **kwargs):
+ self._more_like_this = True
+ self._mlt_instance = model_instance
+
+ def run_mlt(self, **kwargs):
+ """Builds and executes the query. Returns a list of search results."""
+ if self._more_like_this is False or self._mlt_instance is None:
+ raise MoreLikeThisError("No instance was provided to determine 'More Like This' results.")
+
+ additional_query_string = self.build_query()
+ search_kwargs = {
+ 'start_offset': self.start_offset,
+ 'result_class': self.result_class,
+ 'models': self.models,
+ 'mlt.fl': 'tags',
+ }
+
+ if self.end_offset is not None:
+ search_kwargs['end_offset'] = self.end_offset - self.start_offset
+
+ results = self.backend.more_like_this(self._mlt_instance, additional_query_string, **search_kwargs)
+ self._results = results.get('results', [])
+ self._hit_count = results.get('hits', 0)
+
+
+class CustomSolrSearchBackend(haystack.backends.solr_backend.SolrSearchBackend):
+ def more_like_this(self, model_instance, additional_query_string=None,
+ start_offset=0, end_offset=None, models=None,
+ limit_to_registered_models=None, result_class=None, **kwargs):
+ from haystack import connections
+
+ # Deferred models will have a different class ("RealClass_Deferred_fieldname")
+ # which won't be in our registry:
+ model_klass = model_instance._meta.concrete_model
+
+ index = connections[self.connection_alias].get_unified_index().get_index(model_klass)
+ field_name = index.get_content_field()
+ params = {
+ 'fl': '*,score',
+ 'mlt.fl': 'text,title',
+ 'mlt.qf': 'text^0.3 tags^2.0 title^1.0',
+ }
+
+ if start_offset is not None:
+ params['start'] = start_offset
+
+ if end_offset is not None:
+ params['rows'] = end_offset
+
+ narrow_queries = set()
+
+ if limit_to_registered_models is None:
+ limit_to_registered_models = getattr(settings, 'HAYSTACK_LIMIT_TO_REGISTERED_MODELS', True)
+
+ if models and len(models):
+ model_choices = sorted(['%s.%s' % (model._meta.app_label, model._meta.module_name) for model in models])
+ elif limit_to_registered_models:
+ # Using narrow queries, limit the results to only models handled
+ # with the current routers.
+ model_choices = self.build_models_list()
+ else:
+ model_choices = []
+
+ if len(model_choices) > 0:
+ if narrow_queries is None:
+ narrow_queries = set()
+
+ narrow_queries.add('%s:(%s)' % (DJANGO_CT, ' OR '.join(model_choices)))
+
+ if additional_query_string:
+ narrow_queries.add(additional_query_string)
+
+ if narrow_queries:
+ params['fq'] = list(narrow_queries)
+
+ query = "%s:%s" % (ID, get_identifier(model_instance))
+
+ try:
+ raw_results = self.conn.more_like_this(query, field_name, **params)
+ except (IOError, SolrError) as e:
+ if not self.silently_fail:
+ raise
+
+ self.log.error("Failed to fetch More Like This from Solr for document '%s': %s", query, e)
+ raw_results = EmptyResults()
+
+ return self._process_results(raw_results, result_class=result_class)
+
+
+haystack.backends.solr_backend.SolrEngine.query = CustomSolrSearchQuery
+haystack.backends.solr_backend.SolrEngine.backend = CustomSolrSearchBackend
+
from haystack.views import search_view_factory, FacetedSearchView
from haystack.forms import FacetedSearchForm
-from haystack.query import SearchQuerySet
class SearchView(FacetedSearchView):