Moved search method into base search backend

This commit is contained in:
Karl Hobley 2014-06-22 18:56:08 +01:00 committed by Karl Hobley
parent 001fcabb46
commit 08ced063ff
4 changed files with 48 additions and 60 deletions

View file

@ -514,7 +514,7 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, indexed.Index
# Search
s = get_search_backend()
return s.search(query_string, model=cls, fields=fields, filters=filters, prefetch_related=prefetch_related)
return s.search(query_string, cls, fields=fields, filters=filters, prefetch_related=prefetch_related)
@classmethod
def clean_subpage_types(cls):

View file

@ -1,6 +1,9 @@
from django.db import models
from django.db.models.query import QuerySet
from django.core.exceptions import ImproperlyConfigured
from wagtail.wagtailsearch.indexed import Indexed
from wagtail.wagtailsearch.utils import normalise_query_string
class BaseSearch(object):
@ -32,5 +35,38 @@ class BaseSearch(object):
def delete(self, obj):
return NotImplemented
def search(self, query_string, model, fields=None, filters={}, prefetch_related=[]):
def _search(self, queryset, query_string, fields=None):
return NotImplemented
def search(self, query_string, model_or_queryset, fields=None, filters=None, prefetch_related=None):
# Find model/queryset
if isinstance(model_or_queryset, QuerySet):
model = model_or_queryset.model
queryset = model_or_queryset
else:
model = model_or_queryset
queryset = model_or_queryset.objects.all()
# Model must be a descendant of Indexed and be a django model
if not issubclass(model, Indexed) or not issubclass(model, models.Model):
return []
# Normalise query string
if query_string is not None:
query_string = normalise_query_string(query_string)
# Check that theres still a query string after the clean up
if query_string == "":
return []
# Apply filters to queryset
if filters:
queryset = queryset.filter(**filters)
# Prefetch related
if prefetch_related:
for prefetch in prefetch_related:
queryset = queryset.prefetch_related(prefetch)
# Search
return self._search(queryset, query_string, fields=fields)

View file

@ -2,7 +2,6 @@ from django.db import models
from wagtail.wagtailsearch.backends.base import BaseSearch
from wagtail.wagtailsearch.indexed import Indexed
from wagtail.wagtailsearch.utils import normalise_query_string
class DBSearch(BaseSearch):
@ -27,26 +26,16 @@ class DBSearch(BaseSearch):
def delete(self, obj):
pass # Not needed
def search(self, query_string, model, fields=None, filters=None, prefetch_related=None):
# Get fields
if fields is None:
fields = [field.field_name for field in model.get_searchable_search_fields()]
# Start with all objects
query = model.objects.all()
# Apply filters
if filters:
query = query.filter(**filters)
def _search(self, queryset, query_string, fields=None):
if query_string is not None:
# Normalise query string
query_string = normalise_query_string(query_string)
# Get fields
if fields is None:
fields = [field.field_name for field in queryset.model.get_searchable_search_fields()]
# Get terms
terms = query_string.split()
if not terms:
return model.objects.none()
return queryset.model.objects.none()
# Filter by terms
for term in terms:
@ -54,21 +43,16 @@ class DBSearch(BaseSearch):
for field_name in fields:
# Check if the field exists (this will filter out indexed callables)
try:
model._meta.get_field_by_name(field_name)
queryset.model._meta.get_field_by_name(field_name)
except:
continue
# Filter on this field
term_query |= models.Q(**{'%s__icontains' % field_name: term})
query = query.filter(term_query)
queryset = queryset.filter(term_query)
# Distinct
query = query.distinct()
queryset = queryset.distinct()
# Prefetch related
if prefetch_related:
for prefetch in prefetch_related:
query = query.prefetch_related(prefetch)
return query
return queryset

View file

@ -3,14 +3,12 @@ from __future__ import absolute_import
import json
from django.db import models
from django.db.models.query import QuerySet
from elasticsearch import Elasticsearch, NotFoundError, RequestError
from elasticsearch.helpers import bulk
from wagtail.wagtailsearch.backends.base import BaseSearch
from wagtail.wagtailsearch.indexed import Indexed, SearchField, FilterField
from wagtail.wagtailsearch.utils import normalise_query_string
class ElasticSearchMapping(object):
@ -576,35 +574,5 @@ class ElasticSearch(BaseSearch):
except NotFoundError:
pass # Document doesn't exist, ignore this exception
def search(self, query_string, model_or_queryset, fields=None, filters=None, prefetch_related=None):
# Find model/queryset
if isinstance(model_or_queryset, QuerySet):
model = model_or_queryset.model
queryset = model_or_queryset
else:
model = model_or_queryset
queryset = model_or_queryset.objects.all()
# Model must be a descendant of Indexed and be a django model
if not issubclass(model, Indexed) or not issubclass(model, models.Model):
return []
# Normalise query string
if query_string is not None:
query_string = normalise_query_string(query_string)
# Check that theres still a query string after the clean up
if query_string == "":
return []
# Apply filters to queryset
if filters:
queryset = queryset.filter(**filters)
# Prefetch related
if prefetch_related:
for prefetch in prefetch_related:
queryset = queryset.prefetch_related(prefetch)
# Return search results
def _search(self, queryset, query_string, fields=None):
return ElasticSearchResults(self, ElasticSearchQuery(queryset, query_string, fields=fields))