是否可以在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')
目前它只匹配完整的单词。
*%|等字符&安培;没有效果。
或者我必须回到icontains?
https://docs.djangoproject.com/en/1.11/ref/models/querysets/#icontains
感谢任何帮助
答案 0 :(得分:5)
[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)
这样的查询将使用GIN索引(我假设你有一个)。
[Django的部分]我不是Django用户,所以我做了快速研究,发现不幸的是,Django使用plainto_tsquery()
函数,而不是to_tsquery()
:{{3 }}
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)
因此,在这种情况下,我建议您使用to_tsquery()
的纯SQL。但是您需要确保从文本输入中过滤掉所有特殊字符(例如&
或|
),否则to_tsquery()
将产生错误的结果甚至错误。或者,如果可以的话,扩展django.contrib.postgres.search并使用to_tsquery()
(这将是很好的贡献,顺便说一句)。
替代方案是:
LIKE
和使用text_pattern_ops
/ varchar_pattern_ops
运算符类创建的B树索引(如果您需要不区分大小写,使用lower(column_name)
和lower(column_name) like '...%'
上的功能索引;请参阅https://docs.djangoproject.com/en/1.11/_modules/django/contrib/postgres/search/#SearchQuery); 答案 1 :(得分:5)
我扩展了django SearchQuery类,并用plainto_tsquery
覆盖了to_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
现在我可以做类似query = MySearchQuery('whatever:*')