在Haystack搜索中排除对象,无需更新索引
我需要在Haystack搜索中排除一些值为 published=False
的对象。到目前为止,我的做法是添加一个 exclude(published=True)
,像这样:
class MymodelIndex(indexes.RealTimeSearchIndex, indexes.Indexable):
def get_queryset(self):
return Mymodel.objects.all().exclude(published=False)
这样做效果很好,但问题是每次数据库中添加新对象时,我都需要运行 ./manage.py rebuild_index
,这让人觉得很麻烦。
我该如何做到不需要再运行其他命令呢?
备注:
Haystack的索引可以用于很多模型,所以像这样:
search = (
SearchQuerySet().filter(content=term)
)
会返回多种类型的对象,而不仅仅是一个模型。
谢谢
4 个回答
从 haystack 2.4.0 版本开始,你可以使用 haystack.exceptions.SkipDocument
来跳过某些特定的记录,这样就能很方便地通过 index_queryset
来排除它们。
https://github.com/django-haystack/django-haystack/releases/tag/v2.4.0
我最近遇到过类似的事情,真是让人头疼。我找不到其他方法来解决这个问题。
首先,关于Haystack在多个模型上工作的这个问题,过滤器会返回所有匹配项:
Haystack在后台处理模型过滤,它使用一个叫做django_ct的属性来索引,这个属性的值是应用名称和模型名称。在我的情况下,它看起来像这样:django_ct='books.Title'
。
你可以尝试通过以下方式进行过滤:
SearchQuerySet.filter(content=term, django_ct='app.Model')
不过我不确定这样是否有效。在我的情况下,我还是需要进行原始搜索,所以我直接在那个搜索中添加了过滤:
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)
无论你怎么获取,得到你想要的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)
当然,你可以把最后两个查询合并在一起,我只是分开写出来以便更清楚。
代码不算多,但因为各种原因,我花了很长时间才让它正常工作。希望这能对你有所帮助。
感谢@SI Eric,我找到了解决办法,虽然有点小技巧,但确实有效。
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