Django - 全文搜索 - 通配符

fus*_*596 6 django postgresql

是否可以在Django全文搜索中使用通配符?

https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/search/

        post = request.POST.get('search')
        query = SearchQuery(post)
        vector = SearchVector('headline', weight='A') + SearchVector('content', weight='B')
        rank = SearchRank(vector, query, weights=[0.1,0.2])
        data = wiki_entry.objects.annotate(rank=SearchRank(vector,query)).filter(rank__gte=0.1).order_by('-rank')
Run Code Online (Sandbox Code Playgroud)

目前它只匹配完整的单词.

字符如*%| 并没有效果.

或者我必须回到icontains?

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#icontains

任何帮助表示赞赏

use*_*029 7

我延长Django的SEARCHQUERY类并覆盖plainto_tsqueryto_tsquery。做一些简单的测试,就可以了。如果发现导致问题的情况,我会回到这里。

from django.contrib.postgres.search import SearchQuery

class MySearchQuery(SearchQuery):
    def as_sql(self, compiler, connection):
        params = [self.value]
        if self.config:
            config_sql, config_params = compiler.compile(self.config)
            template = 'to_tsquery({}::regconfig, %s)'.format(config_sql)
            params = config_params + [self.value]
        else:
            template = 'to_tsquery(%s)'
        if self.invert:
            template = '!!({})'.format(template)
        return template, params
Run Code Online (Sandbox Code Playgroud)

现在我可以做类似的事情 query = MySearchQuery('whatever:*')

  • 如果有人像我一样在谷歌搜索后来到这里:目前 Django 支持 SearchQuery 的 `search_type` kwarg。像这样: `my_query = SearchQuery("query text", search_type="raw")` (2认同)

Nic*_*ick 6

[Postgres的部分] Postgres的手册提到此仅简单(https://www.postgresql.org/docs/current/static/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES),但是,可能的是,如果你只需要前缀匹配:

test=# select to_tsvector('abcd') @@ to_tsquery('ab:*');
 ?column?
----------
 t
(1 row)


test=# select to_tsvector('abcd') @@ to_tsquery('ac:*');
 ?column?
----------
 f
(1 row)
Run Code Online (Sandbox Code Playgroud)

而这样的查询将利用GIN索引(我假设你有一个).

[Django的部分]我不是Django的用户,所以我做了快速调研,发现,不幸的是,Django使用plainto_tsquery()功能,而不是to_tsquery():https://docs.djangoproject.com/en/1.11/_modules/django/contrib/postgres/搜索/#SEARCHQUERY

plainto_tsquery() 为简单起见,当您仅使用纯文本作为输入时 - 因此它不支持高级查询:

test=# select to_tsvector('abcd') @@ plainto_tsquery('ab:*');
 ?column?
----------
 f
(1 row)

test=# select to_tsvector('abcd') @@ plainto_tsquery('ac:*');
 ?column?
----------
 f
(1 row)
Run Code Online (Sandbox Code Playgroud)

所以在这种情况下,我建议你使用纯SQL to_tsquery().但是你需要确保从文本输入中过滤掉所有特殊字符(如&|),否则 to_tsquery()会产生错误的结果甚至错误.或者,如果你能,延长django.contrib.postgres.search与工作能力to_tsquery()(这将是很大的贡献,顺便说一句).

替代方案是: