Ale*_*lex 5 django full-text-search
我正在建立一个站点,在该站点中我想对某些对象的标题和描述实施文本搜索。由于我的对象数量很少(约500个文档),因此我不考虑使用Haystack之类的东西。
我只需要2个功能:
我研究了django-watson和django-full-text-search,但不确定它们是否允许部分匹配。有任何想法吗?
使用新的全文搜索作为django.contrib.postgres
起点,可以扩展SearchQuery
以创建一个处理最终单词的部分部分搜索的版本:
from psycopg2.extensions import adapt
from django.contrib.postgres.search import SearchQuery
class PrefixedPhraseQuery(SearchQuery):
"""
Alter the tsquery executed by SearchQuery
"""
def as_sql(self, compiler, connection):
# Or <-> available in Postgres 9.6
value = adapt('%s:*' % ' & '.join(self.value.split()))
if self.config:
config_sql, config_params = compiler.compile(self.config)
template = 'to_tsquery({}::regconfig, {})'\
.format(config_sql, value)
params = config_params
else:
template = 'to_tsquery({})'\
.format(value)
params = []
if self.invert:
template = '!!({})'.format(template)
return template, params
Run Code Online (Sandbox Code Playgroud)
然后您可以在查询中使用它,如下所示:
vector = SearchVector(
'first_name',
'last_name',
'email',
config='simple')
query = PrefixedPhraseQuery(query, config='simple')
queryset = queryset\
.annotate(vector=vector)\
.filter(vector=query)
Run Code Online (Sandbox Code Playgroud)
你也可以写一个startswith
lookup,参考实现SearchVectorExact
。
在 Django 的最新版本中,这变得更加简单。SearchQuery
现在有一种raw
可用于请求前缀查询的模式。
query = SearchQuery("search & term & prefix:*", search_type="raw")
results = Model.objects\
.filter(_search_vector=query)\
.annotate(
rank=SearchRank(
F("_search_vector"),
query,
cover_density=True,
)
)
.order_by("-rank")
Run Code Online (Sandbox Code Playgroud)
其中_search_vector
,SearchVectorField
或 可以注释到模型上。
您的网站每秒有多少点击量?每个文档,存储多少个数据?
如果我们谈论的是 500 个文档并且每分钟的点击量很少,也许 django api 就足够了:
q = None
for word in search_string.split():
q_aux = Q( title__icontains = word ) | Q( description__icontains = word )
q = ( q_aux & q ) if bool( q ) else q_aux
result = Document.objects.filter( q )
Run Code Online (Sandbox Code Playgroud)
你曾经考虑过这个选择吗?
当心: