部分关键字搜索和排名

时间:2019-04-02 16:16:22

标签: django postgresql

使用Django和Postgres,我有一个投资控股模型,如下所示:

class Holding(BaseModel):    
    name = models.CharField(max_length=255, db_index=True)
    symbol = models.CharField(max_length=16, db_index=True)
    fund_codes = ArrayField(models.CharField(max_length=16), blank=True, default=list)
    ...

其中包含大约70k美国/加拿大股票,共同基金的清单。我想构建一个自动完成搜索功能,该功能优先1)symbolfund_codes的完全匹配排名,然后是2)symbol上的近匹配,然后3)全文搜索持有name的时间。

如果我有一个搜索向量,可以为symbolfund_codes增加更多的权重:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank
from django.db.models import F, Func, Value

vector = SearchVector('name', weight='D') + \
         SearchVector('symbol', weight='A') + \
         SearchVector(Func(F('fund_codes'), Value(' '), function='array_to_string'), weight='A')

然后,搜索“ MA”

Investment.objects \
    .annotate(document=vector, rank=SearchRank(vector, query)) \
    .filter(document__icontains='MA') \
    .order_by('-rank') \
    .values_list('name', 'fund_codes', 'symbol', 'rank',)

不给出我需要的结果。我需要MA(万事达卡)作为顶部列表,然后是MAS(Masco Corp),等等...然后在name字段中包含“ MA”的列表。

我还研究了覆盖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

但是仍然没有得到我需要的结果。关于在此用例中应如何使用搜索功能的任何建议?也许将精确搜索查询和全文搜索查询连接起来?

1 个答案:

答案 0 :(得分:0)

您需要输入标准化参数。这将为完全匹配的名称提供更高的排名。原始查询如下所示:

SELECT id, name, symbol, func_codes, 
ts_rank_cd(to_tsvector(func_codes), to_tsquery('MA'), 2 ) as rank 
FROM Holding
ORDER BY rank DESC
LIMIT 100;

请注意,我传入了规范化参数https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING


如何在Django中做到这一点?

我相信django尚不支持通过规范化。我看到了一张公开票,但它已经有2年历史了。也许没有人对此进行过研究。
https://code.djangoproject.com/ticket/28194

您现在可以使用原始查询。请参阅官方文档,了解如何: https://docs.djangoproject.com/en/2.2/topics/db/sql/