简体   繁体   English

在Haystack搜索中排除对象而无需update_index

[英]Exclude objects on Haystack search without the need of update_index

I need Haystack search to exclude some objects with value published=False , the way I've managed it so far is by adding an exclude(published=True) as following: 我需要Haystack搜索来排除一些值published=False对象,到目前为止我管理它的方式是添加一个exclude(published=True) ,如下所示:

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 to ./manage.py rebuild_index everytime a new object is added to the database which makes it terrible. 它按预期工作,问题是我每次将新对象添加到数据库时都需要./manage.py rebuild_index ,这使得它很糟糕。

How can I make it without the need to run anything else ? 如何在不需要运行任何其他东西的情况下制作它?

Notes: 笔记:

Indexes on Haystack work for many models, so something like this: Haystack的索引适用于许多模型,如下所示:

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

returns many kinds of objects and not just one model. 返回多种对象而不仅仅是一种模型。

Thanks 谢谢

I recently had to do something similar to this and it was a pain in the arse. 我最近不得不做类似的事情,这是一个痛苦的屁股。 I could not find any other way to do this. 我找不到任何其他方法来做到这一点。

First off to address the issue of Haystack working on many models and so filter returns all matches: 首先解决Haystack在许多模型上工作的问题,因此过滤器返回所有匹配:

Haystack handles model filtering behind the scenes using a property it indexes called django_ct, which equals the app name and model name. Haystack使用其索引名为django_ct的属性处理幕后模型过滤,该属性等于应用程序名称和模型名称。 In my particular case it looked something like django_ct='books.Title' . 在我的特殊情况下,它看起来像django_ct='books.Title'

You could try filtering by doing 您可以尝试过滤

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

But I don't know if it will work that way. 但我不知道它是否会以这种方式运作。 In my particular case I had to do a raw search anyway, so I was able to add the filtering directly to that: 在我的特殊情况下,我不得不做一个原始搜索,所以我能够直接添加过滤:

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)

Regardless of how you get it, after you get your SearchQuerySet that you want to do additional filtering on without updating the index, you have to do it with your own code. 无论你如何得到它,在你想要在不更新索引的情况下进行额外过滤的SearchQuerySet之后,你必须使用自己的代码来完成它。

# 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 split them out to be explicit. 当然,您可以将最后两个查询组合在一起,我只是将它们拆分为显式。

It's not that much code, but it took me a long while to get it working for various reasons. 这不是那么多代码,但是由于各种原因我花了很长时间才使它工作。 Hopefully it helps you out. 希望它可以帮助你。

Since haystack 2.4.0 you can raise haystack.exceptions.SkipDocument to skip individual records which are easily excluded using index_queryset 从haystack 2.4.0开始,你可以引发haystack.exceptions.SkipDocument来跳过使用index_queryset轻松排除的单个记录

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

There is a way to filter by an object in Haystack. 有一种方法可以通过Haystack中的对象进行过滤。 I had a vary similar issue to above and came across the models method in the Haystack SearchQuerySet API docs. 我有一个与上面类似的问题,并且在Haystack SearchQuerySet API文档中遇到了models方法。

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

SearchQuerySet.models(self, *models)

Accepts an arbitrary number of Model classes to include in the search. 接受任意数量的Model类以包含在搜索中。 This will narrow the search results to only include results from the models specified. 这会缩小搜索结果范围,使其仅包含指定模型的结果。

Example: 例:

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

So from here you can filter by content within the object as needed. 因此,您可以根据需要按对象内容进行过滤。

Thanks to @SI Eric, I was able to find an answer, it's also kinda hacky but it works. 感谢@SI Eric,我能够找到答案,它也有点hacky但它​​确实有效。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM