# -*- coding: utf-8 -*-
'''
Created on Jul 30, 2012
@author: ymh
'''
from django.db.models.loading import get_model
from haystack.backends import BaseEngine, SearchResult, elasticsearch_backend
from haystack.constants import DJANGO_CT, DJANGO_ID
from haystack.exceptions import MissingDependency
from haystack.utils import get_identifier
from ldt.ldt_utils.models import Segment
import collections
import datetime
try:
import requests
except ImportError:
raise MissingDependency("The 'elasticsearch' backend requires the installation of 'requests'.")
try:
import pyelasticsearch
except ImportError:
raise MissingDependency("The 'elasticsearch' backend requires the installation of 'pyelasticsearch'. Please refer to the documentation.")
class ElasticsearchSearchBackend(elasticsearch_backend.ElasticsearchSearchBackend):
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):
kwargs = super(ElasticsearchSearchBackend, self).build_search_kwargs(query_string, sort_by=sort_by, start_offset=start_offset, end_offset=end_offset,
fields=fields, highlight=highlight, facets=facets,
date_facets=date_facets, query_facets=query_facets,
narrow_queries=narrow_queries, spelling_query=spelling_query,
within=within, dwithin=dwithin, distance_point=distance_point,
models=models, limit_to_registered_models=limit_to_registered_models,
result_class=result_class)
#TODO : try to make list of field dynamic
#TODO : How to handle multiple
if highlight:
fields_def = { }
if models is None or len(models) == 0 or Segment in models:
fields_def['tags'] = {}
fields_def['title'] = {}
fields_def['abstract'] = {}
kwargs['highlight'] = {
'pre_tags' : ["<span class='highlight'>"],
'post_tags' : ["</span>"],
"number_of_fragments" : 0,
'fields': fields_def
}
return kwargs
def remove(self, obj_or_string, commit=True):
if not self.setup_complete:
try:
self.setup()
except (requests.RequestException, pyelasticsearch.ElasticHttpError), e:
if not self.silently_fail:
raise
self.log.error("Failed to remove document '%s' from Elasticsearch: %s", repr(obj_or_string), e)
return
if isinstance(obj_or_string, collections.Iterable) and not isinstance(obj_or_string, basestring):
ids = [get_identifier(elt) for elt in obj_or_string]
if not ids:
return
q = {'ids' : {'values' : ids}}
self.conn.delete_by_query(self.index_name, 'modelresult', q)
else:
return super(ElasticsearchSearchBackend, self).remove(obj_or_string, commit=commit)
class ElasticsearchSearchEngine(BaseEngine):
backend = ElasticsearchSearchBackend
query = elasticsearch_backend.ElasticsearchSearchQuery