Added new search configuration format

This commit is contained in:
Karl Hobley 2014-06-20 12:41:51 +01:00
parent 1a3558cabd
commit bba9d4faf2
6 changed files with 94 additions and 51 deletions

View file

@ -4,27 +4,20 @@ from django.contrib.contenttypes.models import ContentType
from django.db.models import Count
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from wagtail.wagtailsearch import Indexed, get_search_backend
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch.backends import get_search_backend
class TagSearchable(Indexed):
class TagSearchable(indexed.Indexed):
"""
Mixin to provide a 'search' method, searching on the 'title' field and tags,
for models that provide those things.
"""
indexed_fields = {
'title': {
'type': 'string',
'analyzer': 'edgengram_analyzer',
'boost': 10,
},
'get_tags': {
'type': 'string',
'analyzer': 'edgengram_analyzer',
'boost': 10,
},
}
search_fields = (
indexed.SearchField('title', partial_match=True, boost=10),
indexed.SearchField('get_tags', partial_match=True, boost=10)
)
@property
def get_tags(self):

View file

@ -28,7 +28,8 @@ from treebeard.mp_tree import MP_Node
from wagtail.wagtailcore.utils import camelcase_to_underscore
from wagtail.wagtailcore.query import PageQuerySet
from wagtail.wagtailsearch import Indexed, get_search_backend
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch.backends import get_search_backend
class SiteManager(models.Manager):
@ -260,7 +261,7 @@ class PageBase(models.base.ModelBase):
@python_2_unicode_compatible
class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, Indexed)):
class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, indexed.Indexed)):
title = models.CharField(max_length=255, help_text=_("The page title as you'd like it to be seen by the public"))
slug = models.SlugField(help_text=_("The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/"))
# TODO: enforce uniqueness on slug field per parent (will have to be done at the Django
@ -279,21 +280,11 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, Indexed)):
expire_at = models.DateTimeField(verbose_name=_("Expiry date/time"), help_text=_("Please add a date-time in the form YYYY-MM-DD hh:mm."), blank=True, null=True)
expired = models.BooleanField(default=False, editable=False)
indexed_fields = {
'title': {
'type': 'string',
'analyzer': 'edgengram_analyzer',
'boost': 100,
},
'live': {
'type': 'boolean',
'index': 'not_analyzed',
},
'path': {
'type': 'string',
'index': 'not_analyzed',
},
}
search_fields = (
indexed.SearchField('title', partial_match=True, boost=100),
indexed.FilterField('live'),
indexed.FilterField('path'),
)
def __init__(self, *args, **kwargs):
super(Page, self).__init__(*args, **kwargs)

View file

@ -12,6 +12,7 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import python_2_unicode_compatible
from wagtail.wagtailadmin.taggable import TagSearchable
from wagtail.wagtailsearch import indexed
@python_2_unicode_compatible
@ -23,14 +24,9 @@ class Document(models.Model, TagSearchable):
tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))
indexed_fields = {
'uploaded_by_user_id': {
'type': 'integer',
'store': 'yes',
'indexed': 'no',
'boost': 0,
},
}
search_fields = TagSearchable.search_fields + (
indexed.FilterField('uploaded_by_user'),
)
def __str__(self):
return self.title

View file

@ -20,6 +20,7 @@ from unidecode import unidecode
from wagtail.wagtailadmin.taggable import TagSearchable
from wagtail.wagtailimages.backends import get_image_backend
from wagtail.wagtailsearch import indexed
from .utils import validate_image_format
@ -48,14 +49,9 @@ class AbstractImage(models.Model, TagSearchable):
tags = TaggableManager(help_text=None, blank=True, verbose_name=_('Tags'))
indexed_fields = {
'uploaded_by_user_id': {
'type': 'integer',
'store': 'yes',
'indexed': 'no',
'boost': 0,
},
}
search_fields = TagSearchable.search_fields + (
indexed.FilterField('uploaded_by_user'),
)
def __str__(self):
return self.title

View file

@ -35,6 +35,11 @@ class Indexed(object):
@classmethod
def indexed_get_indexed_fields(cls):
# New way
if hasattr(cls, 'search_fields'):
return dict((field.get_attname(cls), field.to_dict(cls)) for field in cls.search_fields)
# Old way
# Get indexed fields for this class as dictionary
indexed_fields = cls.indexed_fields
if isinstance(indexed_fields, dict):
@ -83,3 +88,58 @@ class Indexed(object):
return doc
indexed_fields = ()
class BaseField(object):
def __init__(self, field_name, **kwargs):
self.field_name = field_name
self.kwargs = kwargs
def get_field(self, cls):
return cls._meta.get_field_by_name(self.field_name)[0]
def get_attname(self, cls):
try:
field = self.get_field(cls)
return field.attname
except models.fields.FieldDoesNotExist:
return self.field_name
def to_dict(self, cls):
dic = {
'type': 'string'
}
if 'es_extra' in self.kwargs:
for key, value in self.kwargs['es_extra'].items():
dic[key] = value
return dic
class SearchField(BaseField):
def __init__(self, field_name, boost=None, partial_match=False, **kwargs):
super(SearchField, self).__init__(field_name, **kwargs)
self.boost = boost
self.partial_match = partial_match
def to_dict(self, cls):
dic = super(SearchField, self).to_dict(cls)
if self.boost and 'boost' not in dic:
dic['boost'] = self.boost
if self.partial_match and 'analyzer' not in dic:
dic['analyzer'] = 'edgengram_analyzer'
return dic
class FilterField(BaseField):
def to_dict(self, cls):
dic = super(FilterField, self).to_dict(cls)
if 'index' not in dic:
dic['index'] = 'not_analyzed'
return dic

View file

@ -4,7 +4,7 @@ from django.db import models
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible
from wagtail.wagtailsearch.indexed import Indexed
from wagtail.wagtailsearch import indexed
from wagtail.wagtailsearch.utils import normalise_query_string, MAX_QUERY_STRING_LENGTH
@ -82,12 +82,17 @@ class EditorsPick(models.Model):
# Used for tests
class SearchTest(models.Model, Indexed):
class SearchTest(models.Model, indexed.Indexed):
title = models.CharField(max_length=255)
content = models.TextField()
live = models.BooleanField(default=False)
indexed_fields = ("title", "content", "callable_indexed_field", "live")
search_fields = (
indexed.SearchField('title'),
indexed.SearchField('content'),
indexed.SearchField('callable_indexed_field'),
indexed.SearchField('live'),
)
def callable_indexed_field(self):
return "Callable"
@ -96,4 +101,6 @@ class SearchTest(models.Model, Indexed):
class SearchTestChild(SearchTest):
extra_content = models.TextField()
indexed_fields = "extra_content"
search_fields = SearchTest.search_fields + (
indexed.SearchField('extra_content'),
)