mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-11 08:43:10 +00:00
Index fields with correct type in ElasticSearch
Previously, everything was converted to a string before indexing in ElasticSearch. This caused issues where certian filters may not work as expected (such as a greater than filter on an integer field) This commit changes this by adding type conversion into the ElasticSearch backend.
This commit is contained in:
parent
673da4ab02
commit
584f5a7049
2 changed files with 49 additions and 9 deletions
|
|
@ -13,6 +13,32 @@ from wagtail.wagtailsearch.utils import normalise_query_string
|
|||
|
||||
|
||||
class ElasticSearchMapping(object):
|
||||
TYPE_MAP = {
|
||||
'AutoField': 'integer',
|
||||
'BinaryField': 'binary',
|
||||
'BooleanField': 'boolean',
|
||||
'CharField': 'string',
|
||||
'CommaSeparatedIntegerField': 'string',
|
||||
'DateField': 'date',
|
||||
'DateTimeField': 'date',
|
||||
'DecimalField': 'double',
|
||||
'FileField': 'string',
|
||||
'FilePathField': 'string',
|
||||
'FloatField': 'double',
|
||||
'IntegerField': 'integer',
|
||||
'BigIntegerField': 'long',
|
||||
'IPAddressField': 'string',
|
||||
'GenericIPAddressField': 'string',
|
||||
'NullBooleanField': 'boolean',
|
||||
'OneToOneField': 'integer',
|
||||
'PositiveIntegerField': 'integer',
|
||||
'PositiveSmallIntegerField': 'integer',
|
||||
'SlugField': 'string',
|
||||
'SmallIntegerField': 'integer',
|
||||
'TextField': 'string',
|
||||
'TimeField': 'date',
|
||||
}
|
||||
|
||||
def __init__(self, model):
|
||||
self.model = model
|
||||
|
||||
|
|
@ -20,7 +46,7 @@ class ElasticSearchMapping(object):
|
|||
return self.model.indexed_get_content_type()
|
||||
|
||||
def get_field_mapping(self, field):
|
||||
mapping = {'type': 'string'}
|
||||
mapping = {'type': self.TYPE_MAP.get(field.get_type(self.model), 'string')}
|
||||
|
||||
if isinstance(field, SearchField):
|
||||
if field.boost:
|
||||
|
|
@ -60,14 +86,8 @@ class ElasticSearchMapping(object):
|
|||
def get_document(self, obj):
|
||||
# Build document
|
||||
doc = dict(pk=str(obj.pk), content_type=self.model.indexed_get_content_type())
|
||||
for field in [field.get_attname(self.model) for field in self.model.get_search_fields()]:
|
||||
if hasattr(obj, field):
|
||||
doc[field] = getattr(obj, field)
|
||||
|
||||
# Check if this field is callable
|
||||
if hasattr(doc[field], '__call__'):
|
||||
# Call it
|
||||
doc[field] = doc[field]()
|
||||
for field in self.model.get_search_fields():
|
||||
doc[field.get_index_name(self.model)] = field.get_value(obj)
|
||||
|
||||
return doc
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,26 @@ class BaseField(object):
|
|||
def get_index_name(self, cls):
|
||||
return self.get_attname(cls) + self.suffix
|
||||
|
||||
def get_type(self, cls):
|
||||
if 'type' in self.kwargs:
|
||||
return self.kwargs['type']
|
||||
|
||||
try:
|
||||
field = self.get_field(cls)
|
||||
return field.get_internal_type()
|
||||
except models.fields.FieldDoesNotExist:
|
||||
return 'CharField'
|
||||
|
||||
def get_value(self, obj):
|
||||
try:
|
||||
field = self.get_field(obj.__class__)
|
||||
return field._get_val_from_obj(obj)
|
||||
except models.fields.FieldDoesNotExist:
|
||||
value = getattr(obj, self.field_name, None)
|
||||
if hasattr(value, '__call__'):
|
||||
value = value()
|
||||
return value
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s: %s>' % (self.__class__.__name__, self.field_name)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue