Exclude objects in Haystack search without the need for update_index

I need a Haystack search to exclude some objects with a value of published=False , since I still managed it by adding exclude(published=True) as follows:

 class MymodelIndex(indexes.RealTimeSearchIndex, indexes.Indexable): def get_queryset(self): return Mymodel.objects.all().exclude(published=False) 

It works as expected, the problem is that I need ./manage.py rebuild_index every time a new object is added to the database, which makes it terrible.

How can I do this without having to run anything else?

Notes:

Haystack indexes work for many models, so something like this:

 search = ( SearchQuerySet().filter(content=term) ) 

returns many kinds of objects, not just one model.

thanks

+4
source share
4 answers

Thanks to @SI Eric, I was able to find the answer, this is also a curious hacking, but it works.

 search = ( SearchQuerySet().filter(content=term) ) search_list = search[:] unpublished_Mymodels = Mymodel.objects.filter(published=False) for match in search_list: try: if match.model_name == 'Mymodel': if match._get_object() in unpublished_Mymodels: search_list.remove(match) except: pass search = search_list 
0
source

I recently had to do something similar, and it was a pain in the ass. I could not find another way to do this.

First of all, to solve the Haystack problem, which works on many models, and therefore the filter returns all matches:

Haystack handles filtering the model behind the scenes using a property that it indexes as django_ct, which is equal to the application name and model name. In my particular case, it looked like django_ct='books.Title' .

You can try filtering by doing

 SearchQuerySet.filter(content=term, django_ct='app.Model') 

But I don’t know if this will work like that. In my specific case, I still had to do an raw search, so I managed to add filtering directly to this:

 sqs = SearchQuerySet() sqs = sqs.raw_search(u'(title:(%s)^500 OR author:"%s"^400 OR "%s"~2 OR (%s)) AND (django_ct:books.Title)' % term) 

No matter how you get it, after you get the SearchQuerySet that you want to do additional filtering without updating the index, you have to do it with your own code.

 # each item in a queryset has a pk property to the model instance it references pks = [item.pk for item in list(sqs)] # have to wrap sqs in a list otherwise it causes problems # use those pks to create a standard django queryset object results = Model.objects.filter(pk__in=pks) # Now you can do any additional filtering like normal results = results.exclude(published=False) 

Of course, you can combine the last two queries, I just divided them into explicit ones.

This is not a lot of code, but it took me a long time to get it working for various reasons. Hope this helps you.

+3
source

There is a way to filter an object in Haystack. I had a similar problem described above and met the models method in Haystack SearchQuerySet API SearchQuerySet .

From Haystack ( http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#models )

SearchQuerySet.models(self, *models)

Accepts an arbitrary number of model classes that must be included in the search. This will narrow the search results so that they include results only from the specified models.

Example:

SearchQuerySet().filter(content='foo').models(BlogEntry, Comment)

So, from here you can filter by content inside the object as needed.

+1
source

With haystack 2.4.0 you can raise haystack.exceptions.SkipDocument to skip individual entries that are easy to exclude with index_queryset

https://github.com/django-haystack/django-haystack/releases/tag/v2.4.0

+1
source

Source: https://habr.com/ru/post/1468847/


All Articles