【问题标题】:Filter Django Haystack results like QuerySet?像 QuerySet 一样过滤 Django Haystack 结果?
【发布时间】:2011-01-10 16:37:35
【问题描述】:

是否可以将 Django Haystack 搜索与“内置”QuerySet 过滤操作结合起来,特别是使用 SearchQuerySet 不支持的 Q() 实例和查找类型进行过滤?以任一顺序:

haystack-searched -> queryset-filtered

queryset-filtered -> haystack-searched

浏览 Django Haystack 文档并没有给出如何执行此操作的任何说明。

【问题讨论】:

    标签: django django-queryset django-haystack


    【解决方案1】:

    您可以使用对象的 PK,根据 Haystack 搜索的结果过滤您的查询集:

    def view(request):
      if request.GET.get('q'):
        from haystack import ModelSearchForm
        form = ModelSearchForm(request.GET, searchqueryset=None, load_all=True)
        searchqueryset = form.search()
        results = [ r.pk for r in searchqueryset ]
    
        docs = Document.objects.filter(pk__in=results)
        # do something with your plain old regular queryset
    
        return render_to_response('results.html', {'documents': docs});
    

    不确定这是如何扩展的,但对于小型结果集(在我的情况下为几百个),这可以正常工作。

    【讨论】:

    • 这样,你的结果会按照ID排序,你会失去针对性。
    • @dzen 那么在保持相关性排名的同时最好的方法是什么?
    • 这无法扩展。我认为查询太长了——有几千个 id 会有 0 个结果。
    【解决方案2】:

    如果你想跟上针对性,你必须通过“对象”从数据库中访问对象:

    模板中的示例:

    {% for result in results %}
        {{ result.object.title }}
        {{ result.objects.author }}
    {% endfor %}
    

    但这真的很糟糕,因为 haystack 会在每个结果上发出一个额外的请求,例如“SELECT * FROM blah WHERE id = 42”。

    您似乎正在尝试从数据库中获取这些对象,因为您没有在索引中添加一些额外的字段,不是吗?如果您在 SearchIndex 中添加标题和作者,那么您可以使用您的结果:

    {% for result in results %}
        {{ result.title }}
        {{ result.author }}
    {% endfor %}
    

    并避免一些额外的查询。

    【讨论】:

    • 如果您运行 searchqueryset.load_all(),那么所有对象都将尽可能高效地从数据库中预加载,而不是一次一个。
    • 使用类似 "SELECT * FROM bla WHERE id in (12, 132,1251)" 的东西,打开(也许)一个新套接字,从那里获取数据是否有效?
    【解决方案3】:

    来自文档:

    SearchQuerySet.load_all(self)

    有效地填充搜索结果中的对象。不使用 这种方法,数据库查找是在每个对象的基础上完成的,导致 许多个人访问数据库。如果使用 load_all,则 SearchQuerySet 会将相似的对象分组到一个查询中, 只产生与不同对象类型一样多的查询 返回。

    http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#load-all

    因此,在您拥有过滤后的 SQS 后,您可以对其执行 load_all() 并通过 SearchResult.object 访问数据库对象。例如。

    sqs = SearchQuerySet()
    # filter as needed, then load_all
    sqs = sqs.load_all()
    
    for result in sqs:
        my_obj = result.object
        # my_obj is a your model object
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-13
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 2018-01-05
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多