在模型(Django 2.1)的多个字段上执行全文搜索

时间:2019-01-22 14:15:27

标签: django

我想对模型中的两个字段执行全文搜索。这是我当前的代码:

if 'keyword' in request.GET:
    search_term = request.GET['keyword']
    vector = SearchVector('Title', weight='A') + SearchVector('Content', weight='B')
    articles = articles.annotate(similarity=TrigramSimilarity(vector, search_term),).filter(similarity__gt=0.01).order_by('-similarity')

此代码返回错误消息

function similarity(tsvector, unknown) does not exist

我认为这是因为我没有正确组合字段,因为当我仅将单个字段替换为vector时,它就可以正常工作。如果pg_trgm扩展名未正确安装,则Trigram搜索将无法在一个字段上进行,对吗?在多个字段中进行搜索的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

我误解了您的问题,该错误表明您已经安装了similarity函数,但是说您不能在similarity函数中使用搜索向量。由于要搜索相似度高于阈值的模式,因此可以分别计算每个字段的相似度并返回最大值。您不能将它们与等级结合在一起。试试这个:

from django.db.models.functions import Greatest

articles.annotate(
    similarity=Greatest(
         TrigramSimilarity('Title', search_term), 
         TrigramSimilarity('Content', search_term)
    )).filter(similarity__gte=0.1).order_by('-similarity')

如果您想给“标题”赋予更高的权重,则可以使用数学函数进行包装以增加权重,而不必使用Greatest

A = 1.0; B = 0.4
articles.annotate(
    similarity=(A/(A+B) * TrigramSimilarity('Title', search_term) 
               + B/(A+B) * TrigramSimilarity('Content', search_term))
    ).filter(similarity__gte=0.1).order_by('-similarity')

请注意,如果{Title}与Greatest的匹配度很高,而'Content'的匹配度不高,则后者会降低相似度值,因此您可能希望将阈值设置得较低。

注意2:相似性会查看完整的字符串,因此,如果您有一段较长的文字(“内容”)并且仅搜索一个关键字,即使该关键字包含在“内容”中,相似性也将返回0 。对于全文搜索,最好将SearchRankSearchVector一起使用。

答案 1 :(得分:0)

我相信您需要在数据库中安装pg_trgm扩展名。 CouchDB mailing list表示必须使用这些功能。

docs

from django.contrib.postgres.operations import TrigramExtension

operations = [TrigramExtension()]