简体   繁体   English

如何使用db查询过滤haystack结果

[英]How to filter haystack results with db query

I need to text-search across my model and filter with db queries at the same time. 我需要在我的模型中进行文本搜索并同时使用db查询进行过滤。

For example: 例如:

class MyModel(models.Model):
    text = models.TextField()
    users = models.ManyToMany(User)

class MyModelIndexIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, model_attr='text')

    def get_model(self):
        return MyModel

So I want to filter all MyModel objects by user AND by some text via full-text search. 所以我希望按用户和所有文本通过全文搜索过滤所有MyModel对象。 Smth like these: Smth喜欢这些:

qs = MyModel.objects.filter(users=request.user)
sqs = MyModelIndex.objects.filter(text=request.GET['q'])
intersection = some_magic_function(qs, sqs)

or 要么

intersection = some_other_magic_function(
    qs_kwargs={'users': request.user},
    sqs_kwargs={'text': request.GET['q']}
)

Of course desired db queries could be much more complicated. 当然,期望的数据库查询可能要复杂得多。

I see some possible solutions, all with major flaws: 我看到一些可能的解决方案,都有重大缺陷:

  1. Make intersection in django: extract ids from qs and use them in sqs filter or vice versa. 在django中进行交集:从qs中提取id并在sqs过滤器中使用它们,反之亦然。 Problem: performance. 问题:表现。 We can workaround itby using pagination and do intersection only for given page and its predecessors. 我们可以通过使用分页来解决它,并且仅对给定页面及其前身进行交集。 In this case we lose total count ( 在这种情况下,我们失去了总数(

  2. Index all m2m related fields. 索引所有m2m相关字段。 Problem: performance, duplicate functionality (I believe db will do such queries much better), db-features such as annotations etc. 问题:性能,重复功能(我相信db会更好地执行此类查询),db-features(如注释等)。

  3. Do not use haystack ( Go for mysql or posgresql built-in full-text search. 不要使用haystack(Go for mysql或posgresql内置全文搜索。

I believe I miss something obvious. 我相信我会错过一些明显的东西 Case seems to be quite common. 案例似乎很常见。 Is there a conventional solution? 有传统的解决方案吗?

In the general case, it's (probably) not possible to solve your problem using just one query. 在一般情况下,它(可能)不可能只使用一个查询来解决您的问题。 For instance, if you are using ElasticSearch as a search backend engine and MySQL for django models, there is no way MySQL and ElasticSearch will communicate to produce a single, common query. 例如,如果您将ElasticSearch用作搜索后端引擎而MySQL用于django模型,则MySQL和ElasticSearch无法通信以生成单个常见查询。

However, there should be a workaround if you are using a common SQL database for your Django models and your Haystack backend engine. 但是,如果您为Django模型和Haystack后端引擎使用通用SQL数据库,则应该有一个解决方法。 You would have to create a custom haystack engine that would parse the query and filter the available models. 您必须创建一个自定义干草堆引擎来解析查询并过滤可用的模型。

For example, to modify the behaviour of the SimpleSearchBackend, all you need to do is patch the search method: 例如,要修改SimpleSearchBackend的行为,您需要做的就是修补search方法:

class CustomSimpleSearchBackend(haystack.backends.SimpleSearchBackend):

    def search(self, query_string, **kwargs):
        ...
        if query_string:
            for model in models:
                ...
                if 'users' in kwargs:
                    qs = qs.filter(users=kwargs['users'])
                ...

class CustomSimpleEngine(haystack.backends.BaseEngine):
    backend = CustomSimpleSearchBackend
    query = haystack.backends.simple_backend.SimpleSearchQuery

And in settings.py: 在settings.py中:

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'myapp.backends.CustomSimpleEngine',
    },
}

Depending on which connection backend you use, the required patch will be different of course, but I suspect it should not be too hard to implement. 根据您使用的连接后端,所需的补丁当然会有所不同,但我怀疑它不应该太难实现。

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

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