Created
November 29, 2015 17:13
-
-
Save GrigoriyMikhalkin/f76be703bc53380986a0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.conf import settings | |
from .query import (ConfigurableSearchQuerySet, | |
ConfigurableElasticSearchQuery) | |
from haystack.backends.elasticsearch_backend import \ | |
ElasticsearchSearchBackend, ElasticsearchSearchEngine | |
# It's modification of ElasticStack code | |
# https://github.com/bennylope/elasticstack/blob/master/elasticstack/backends.py | |
class ConfigurableElasticBackend(ElasticsearchSearchBackend): | |
""" | |
Extends the Haystack ElasticSearch backend to allow configuration of index | |
mappings and field-by-field analyzers. | |
""" | |
DEFAULT_ANALYZER = "snowball" | |
def __init__(self, connection_alias, **connection_options): | |
super(ConfigurableElasticBackend, self).__init__(connection_alias, **connection_options) | |
user_settings = getattr(settings, "ELASTICSEARCH_INDEX_SETTINGS", None) | |
user_analyzer = getattr(settings, "ELASTICSEARCH_DEFAULT_ANALYZER", None) | |
#user_field_mapping = getattr(settings, "ELASTICSEARCH_") | |
if user_settings: | |
setattr(self, "DEFAULT_SETTINGS", user_settings) | |
if user_analyzer: | |
setattr(self, "DEFAULT_ANALYZER", user_analyzer) | |
def build_schema(self, fields): | |
content_field_name, mapping = super(ConfigurableElasticBackend, self).build_schema(fields) | |
for field_name, field_class in fields.items(): | |
field_mapping = mapping[field_class.index_fieldname] | |
if field_mapping["type"] == "string" and field_class.indexed: | |
if not hasattr(field_class, "facet_for") and not field_class.field_type in("ngram", "edge_ngram"): | |
field_mapping["analyzer"] = getattr(field_class, "analyzer", self.DEFAULT_ANALYZER) | |
additional_options = getattr(field_class, "add", None) | |
field_mapping.update( additional_options if additional_options else {} ) | |
mapping.update({field_class.index_fieldname: field_mapping}) | |
return (content_field_name, mapping) | |
def build_search_kwargs(self, query_string, sort_by=None, start_offset=0, end_offset=None, | |
fields='', highlight=False, facets=None, | |
date_facets=None, query_facets=None, | |
narrow_queries=None, spelling_query=None, | |
within=None, dwithin=None, distance_point=None, | |
models=None, limit_to_registered_models=None, | |
result_class=None, search_text=None): | |
out = super(ConfigurableElasticBackend, self).build_search_kwargs(query_string, sort_by, start_offset, end_offset, fields, highlight, facets, date_facets, query_facets, narrow_queries, spelling_query, within, dwithin, distance_point, models, limit_to_registered_models, result_class) | |
try: | |
out["sort"] | |
except KeyError: | |
out["sort"] = [{ | |
"_script": { | |
"script_file": "score_script", | |
"type": "number", | |
"order": "asc", | |
"params": { | |
"q": search_text["search_text"] | |
} | |
} | |
}] | |
return out | |
class ConfigurableElasticSearchEngine(ElasticsearchSearchEngine): | |
backend = ConfigurableElasticBackend | |
query = ConfigurableElasticSearchQuery |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from haystack.fields import CharField as BaseCharField | |
# It's modification of ElasticStack code | |
# https://github.com/bennylope/elasticstack/blob/master/elasticstack/fields.py | |
class ConfigurableFieldMixin(object): | |
""" | |
A mixin which allows specifying the analyzer on a per field basis. | |
""" | |
def __init__(self, **kwargs): | |
self.analyzer = kwargs.pop("analyzer", None) | |
self.add = kwargs.pop("add", None) | |
if self.analyzer is None: | |
raise ValueError("Configurable fields must have an analyzer type") | |
super(ConfigurableFieldMixin, self).__init__(**kwargs) | |
class CharField(ConfigurableFieldMixin, BaseCharField): | |
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from haystack.query import SearchQuerySet | |
from haystack.constants import DEFAULT_ALIAS, DJANGO_CT | |
from haystack.backends.elasticsearch_backend import ElasticsearchSearchQuery | |
class ConfigurableSearchQuerySet(SearchQuerySet): | |
def custom_search(self,search_text=None): | |
clone=self._clone() | |
clone.query.add_custom_search(search_text) | |
return clone | |
class ConfigurableElasticSearchQuery(ElasticsearchSearchQuery): | |
def __init__(self,using=DEFAULT_ALIAS): | |
out=super(ConfigurableElasticSearchQuery,self).__init__(using) | |
self.search_text = {} | |
def add_custom_search(self,search_text=None): | |
self.search_text = { "search_text": search_text } | |
def build_params(self,spelling_query=None,**kwargs): | |
search_kwargs = super(ConfigurableElasticSearchQuery,self).build_params(spelling_query, **kwargs) | |
search_kwargs["search_text"] = self.search_text | |
return search_kwargs | |
def _clone(self,klass=None,using=None): | |
clone = super(ConfigurableElasticSearchQuery,self)._clone(klass,using) | |
clone.search_text = self.search_text | |
return clone |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment