Haystack Django Elasticsearch spelling - django

I have two problems setting up haystack/django/elasticsearch
I never get results from index fields, e.g. indexes.CharField(model_attr='title') doesn't get me results. Only if I put {{ object.title }} in my txt template I get results for matching titles
If my title is 'foo' I never get results for 'fo', while I do have the INCLUDE_SPELLING setting set to True in my backend setting.
The documentation doesn't state anything special about these cases, my setup is per the haystack documentation, what am I missing?
My index:
class FooIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title') # never gets me results unless I add it to the template
def get_model(self):
return Foo
My settings:
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://127.0.0.1:9200/',
'INDEX_NAME': 'haystack',
'INCLUDE_SPELLING': True,
},
}

1) If you have use_template=True only index what you put in the template file so put all the fields you want indexed in there.
2) Did you refresh the index after adding INCLUDE_SPELLING ?

Make sure you enabled spellcheck component.
The first thing to do is create a special field on your SearchIndex class that mirrors the text field, but uses FacetCharField. This disables the post-processing that Solr does, which can mess up your suggestions. Something like the following is suggested:
class MySearchIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
# ... normal fields then...
suggestions = indexes.FacetCharField()
def prepare(self, obj):
prepared_data = super(MySearchIndex, self).prepare(obj)
prepared_data['suggestions'] = prepared_data['text']
return prepared_data
Once this is done, spelling_suggestions method should return the appropriate values.

Related

django datepicker format change

Im trying to change the datepicker format from mm/dd/yyyy to dd-mm-yyyy. So far I've added DATE_INPUT_FORMATS in settings.py to ['%d-%m-%Y'], but this didnt change anything. I also changing it via jquery based on proposed solution in this site but it didnt help also.
<script type="text/javascript">
$(function () {
$('#datepicker').datepicker({ dateFormat: 'dd-mm-yy' });
});
</script>
Its quite a trivial problem but I cant seem to find a way how to solve it.
forms.py
class Calendar(forms.DateInput):
input_type = 'date'
class AdForm(forms.ModelForm):
time_limit = forms.DateInput(format=['%d-%m-%Y'])
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['time_limit'].widget.attrs.update({'class': 'form-control mb-3 datepicker'})
class Meta:
model = Ad
fields = ('time_limit')
widgets = {
'time_limit': Calendar(),
}
The result is still as such:
You can customize the DATE_INPUT_FORMATS creating a formats folder under your main project dir and then adding a custon format file for each language you need as describer in the official Django doc.
You can see how to customize the FORMAT_MODULE_PATH and what is the full list of the (editable) available formats here.
Sample folder structure to edit the english format:
mysite/
formats/
__init__.py
en/
__init__.py
formats.py
And then the formats.py
DATE_FORMAT = 'j N, Y'
In the settings.py file
LANGUAGE_CODE = 'en-us'
USE_L10N = True
FORMAT_MODULE_PATH = [
'my_app.formats',
]

Unable to search part of a term with Django Haystack and Elasticsearch

I have a project based on
Django==1.9.2
django-haystack==2.4.1
elasticsearch==2.2.0
A very simple search view:
def search_view(request):
query = request.GET.get('q', '')
sqs = SearchQuerySet().filter(content=query)
params = {
'results': sqs,
'query': query,
}
return render_to_response('results.html', params,
context_instance=RequestContext(request))
My search index is as simple as:
class CategoryIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
name = indexes.CharField(model_attr='name')
def get_model(self):
return Category
def index_queryset(self, using=None):
return self.get_model().objects.filter(published=True)
The category_text.txt file is just:
{{ object.name }}
In my database I have a few items:
Acqua
Acquario
Aceto
Accento
When I search with my view, I have strange behaviours.
Searching with query "ac" I receive no results! I was expecting to have all my items. I have tryed to change the query using .filter(content__contains=query) (I know it is the default!) but nothing changed.
Searching with query "acqua" I receive 1 result (correct) with the result object, but when I try to print it, the result.object field is None (the other fields contain the correct information).
What am I doing wrong?
Thank you.
UPDATE
I have found a solution to my problem number 2. Latest Haystack version from PyPi is not Django 1.9.x compatible.
I have just added -e git+https://github.com/django-haystack/django-haystack.git#egg=django-haystack to my requirements.txt file and the issue is fixed. More info about that on GitHub: https://github.com/django-haystack/django-haystack/issues/1291
The other issues is still opened and I cannot find any solution to it.
It sounds like you may be running into a minimum number of characters issue for #1. Take a look at the Haystack documents for autocomplete which shows an approach using EdgeNgramField instead of the typical CharField.

Django haystack with elasticsearch SearchQuerySet returns None

I have default django user model which i want to index using elasticsearch
I'm using django-haystack.
in settings.py
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 12
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://127.0.0.1:9200/',
'INDEX_NAME': 'haystack',
},
}
in search_indexes.py
import datetime
from haystack import indexes
from django.contrib.auth.models import User
class UserIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True)
first_name = indexes.CharField(model_attr='first_name', null=True)
last_name = indexes.CharField(model_attr='last_name', null=True)
def get_model(self):
return User
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.all()
and build the index using python manage.py rebuild_index
now in shell
from haystack.query import SearchQuerySet
SearchQuerySet().all()
it returns all the indexed objects (I can confirm the count is same as number of entries in db)
when I do
SearchQuerySet().filter(first_name='Wendy') It returns two results object which is again as expected.
but when I try SearchQuerySet().filter(content='Wendy') it returns None.
basically I want to create an API, in which we can pass a query param and return all the user objects that contains this query string in any field.
http://localhost/search/?q=Wendy
This is my first time I'm using Elasticsearch or (anysearch engine with haystack) so I'm not able to understand what is going on.
After little bit search I found few threads on stack overflow which suggests to use Ngram or EdgeNgram but again those also couldn't work.(I rebuilded the whole index). I even tried content_auto in filter but no success.
Any help or lead will be appreciated.
I was following this official docs.
http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#quick-start
PS: I wrote here only two fields (firstname, lastname) but there are couple more fields in my actual code. its just to write here.
PPS: I'm using Django 1.9. could that be an issue?
This is how my view looks like
def search_api(request):
query = request.GET.get('q')
sqs = SearchQuerySet().filter(content=query)
data = map(lambda x: x.get_stored_fields(), sqs)
return HttpResponse(json.dumps(data))

I don't understand the results that's returning from elasticsearch/haystack

The results that are being returned from haystack, using an elasticsearch backend seem erroneous to me. My search index is as follows:
from haystack import indexes
from .models import IosVideo
class VideoIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title')
absolute_url = indexes.CharField(model_attr='get_absolute_url')
# content_auto = indexes.EdgeNgramField(model_attr='title')
description = indexes.CharField(model_attr='description')
# thumbnail = indexes.CharField(model_attr='thumbnail_url', null=True)
def get_model(self):
return IosVideo
def index_queryset(self, using=None):
return self.get_model().objects.filter(private=False)
My text document looks like:
{{ object.title }}
{{ object.text }}
{{ object.description }}
My query is
SearchQuerySet().models(IosVideo).filter(content="darby")[0]
The result that's returning that makes me think this is not working is a video object with the following characteristics
title: u'Cindy Daniels'
description: u'',
text: u'Cindy Daniels\n\n\n',
absolute_url: u'/videos/testimonial/cindy-daniels/'
Why in the world would the query return such a result? I'm very confused.
My current theory is that it's tokenizing every subset of the char in the query and using that as partial match. Is there a way to decrease this tolerance to be a closer match.
My pip info is
elasticsearch==1.2.0
django-haystack==2.3.1
And the elasticsearch version number is 1.3.1
Additionally when I hit the local server with
http://localhost:9200/haystack/_search/?q=darby&pretty
It returns 10 results.
SearchQuerySet().filter(content="darby")
Returns 4k results.
Does any one know what would cause this type of behavior?
There is a problem with the filter() method on Charfield indexes for django-haystack 2.1.0. You can change them to NgramField instead, for example text = indexes.NgramField(document=True, template_name=True).
The problem is that when you use this combination you get just the first character. So it returns you all the matches that has a 'd' in their text index field.

Django-haystack without attribute '_fields'

I'm making my blog on Django and I want to add site search based on django-haystack. I made a basic configuration of haystack, using official manuals, but when I want to test my search, I'm getting an error: 'Options' object has no attribute '_fields'
Here are some of my configs:
search_indexes.py
class PostIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title')
pub_date = indexes.DateTimeField(model_attr='date')
def get_model(self):
return Post
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.all()
settings.py
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
},
}
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
So this is my problem. Does anyone worked with smth similar? Thanks in advance!
You are hitting a bug in the simple backend which is fixed in git. There doesn't seem to be a release which contains this fix, though, so you can either upgrade to the development version:
pip install -e git+https://github.com/toastdriven/django-haystack.git#master#egg=django-haystack
Or use a different backend (elasticsearch, solr, ...)