def faceted_search( cls, query, user, projects_list=None, versions_list=None, filter_by_user=True ): from readthedocs.search.faceted_search import PageSearch kwargs = { 'user': user, 'query': query, 'filter_by_user': filter_by_user, } filters = {} if projects_list is not None: filters['project'] = projects_list if versions_list is not None: filters['version'] = versions_list kwargs['filters'] = filters return PageSearch(**kwargs)
def get_queryset(self): """ Return Elasticsearch DSL Search object instead of Django Queryset. Django Queryset and elasticsearch-dsl ``Search`` object is similar pattern. So for searching, its possible to return ``Search`` object instead of queryset. The ``filter_backends`` and ``pagination_class`` is compatible with ``Search`` """ # Validate all the required params are there self.validate_query_params() query = self.request.query_params.get('q', '') kwargs = {'filter_by_user': False, 'filters': {}} kwargs['filters']['project'] = [ p.slug for p in self.get_all_projects() ] kwargs['filters']['version'] = self.request.query_params.get('version') if not kwargs['filters']['project']: raise ValidationError("Unable to find a project to search") if not kwargs['filters']['version']: raise ValidationError("Unable to find a version to search") user = self.request.user queryset = PageSearch(query=query, user=user, **kwargs) return queryset
def elastic_search(request, project_slug=None): """ Global user search on the dashboard This is for both the main search and project search. :param project_slug: Sent when the view is a project search """ request_type = None if project_slug: queryset = Project.objects.protected(request.user) project_obj = get_object_or_404(queryset, slug=project_slug) request_type = request.GET.get('type', 'file') user_input = UserInput( query=request.GET.get('q'), type=request_type or request.GET.get('type', 'project'), project=project_slug or request.GET.get('project'), version=request.GET.get('version', LATEST), taxonomy=request.GET.get('taxonomy'), language=request.GET.get('language'), role_name=request.GET.get('role_name'), index=request.GET.get('index'), ) results = '' facets = {} if user_input.query: kwargs = {} for avail_facet in ALL_FACETS: value = getattr(user_input, avail_facet, None) if value: kwargs[avail_facet] = value if user_input.type == 'project': search = ProjectSearch(query=user_input.query, user=request.user, **kwargs) elif user_input.type == 'domain': search = DomainSearch(query=user_input.query, user=request.user, **kwargs) elif user_input.type == 'file': search = PageSearch(query=user_input.query, user=request.user, **kwargs) elif user_input.type == 'all': search = AllSearch(query=user_input.query, user=request.user, **kwargs) results = search[:50].execute() facets = results.facets log.info( LOG_TEMPLATE.format( user=request.user, project=user_input.project or '', type=user_input.type or '', version=user_input.version or '', language=user_input.language or '', msg=user_input.query or '', ), ) # Make sure our selected facets are displayed even when they return 0 results for avail_facet in ALL_FACETS: value = getattr(user_input, avail_facet) if not value or avail_facet not in facets: continue if value not in [val[0] for val in facets[avail_facet]]: facets[avail_facet].insert(0, (value, 0, True)) if results: if user_input.type == 'file': # Change results to turn newlines in highlight into periods # https://github.com/rtfd/readthedocs.org/issues/5168 for result in results: if hasattr(result.meta.highlight, 'content'): result.meta.highlight.content = [ result.replace('\n', '. ') for result in result.meta.highlight.content ] log.debug('Search results: %s', pformat(results.to_dict())) log.debug('Search facets: %s', pformat(results.facets.to_dict())) template_vars = user_input._asdict() template_vars.update({ 'results': results, 'facets': facets, }) if project_slug: template_vars.update({'project_obj': project_obj}) return render( request, 'search/elastic_search.html', template_vars, )