我需要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)
)
返回多种对象,而不仅仅是一种模型。
由于
答案 0 :(得分:3)
我最近不得不做类似的事情,这是一个痛苦的屁股。我找不到任何其他方法来做到这一点。
首先解决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)
当然,您可以将最后两个查询组合在一起,我只是将它们拆分为显式。
这不是那么多代码,但是由于各种原因我花了很长时间才使它工作。希望它可以帮助你。
答案 1 :(得分:2)
自haystack 2.4.0起,您可以提升haystack.exceptions.SkipDocument
以跳过使用index_queryset
轻松排除的个人记录
https://github.com/django-haystack/django-haystack/releases/tag/v2.4.0
答案 2 :(得分:1)
有一种方法可以在Haystack中按对象进行过滤。我遇到了与上述类似的问题,并在Haystack models
API文档中遇到了SearchQuerySet
方法。
来自Haystack(http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#models)
SearchQuerySet.models(self, *models)
接受要包含在搜索中的任意数量的Model类。这会将搜索结果缩小到仅包含指定模型的结果。
示例:
SearchQuerySet().filter(content='foo').models(BlogEntry, Comment)
因此,您可以根据需要按对象内容进行过滤。
答案 3 :(得分:0)
感谢@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