【问题标题】:Performing full text search on more than one field from model (Django 2.1)对模型中的多个字段执行全文搜索(Django 2.1)
【发布时间】:2019-01-22 14:15:26
【问题描述】:

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

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 搜索就不能在一个字段上工作,对吧?在多个领域中搜索的正确方法是什么?

【问题讨论】:

  • 更好的方法是使用 Q 对象:docs.djangoproject.com/en/2.1/topics/db/queries/…
  • @Ahtisham 不能仅使用 Q 进行全文搜索。OP 是正确的,答案如下。
  • @dirkgroten 我很困惑。所以 Q 不是解决方案吗?您能否详细说明如何正确地对多个字段进行全文搜索?提前致谢
  • @dirkgroten 我知道问题不在于没有安装 pg_trgm,因为只有一个字段时三元组搜索有效;只有当我尝试组合字段时它才不起作用,所以我认为我组合它们是错误的。如果我只用一个字段代替“矢量”,它就可以完美地工作

标签: django


【解决方案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' 中有很好的匹配,而 'Content' 中没有与 Greatest 匹配,后者会降低相似度值,因此您可能希望将阈值设置得更低。

注意2:相似度查看完整的字符串,因此如果您有很长的文本('Content')并且只有一个关键字要搜索,即使关键字包含在'Content'中,相似度也会返回 0 .对于全文搜索,您最好使用SearchRankSearchVector

【讨论】:

  • 感谢您的详细说明!我尝试了这些解决方案。第一个返回错误(“Greatest”未定义“)。有这个库吗?第二个没有错误消息,只是按照数据库中设置的顺序返回数据库中的所有内容
  • 我不知道为什么第二种方法会返回所有对象,您需要分别检查“标题”和“内容”的个别相似性(使用.values('similarity') 列出值你的控制台)。
  • 我添加了导入,现在两种解决方案都按照数据库中设置的顺序返回数据库中的所有内容。我认为我的第二个领域有问题。我会调查并回复你。感谢您的时间和耐心!
  • 如果查询不返回任何内容或全部返回,请尝试调整相似度阈值。 0.03 对我有用。
【解决方案2】:

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

Create an empty migration and use the following operation:

from django.contrib.postgres.operations import TrigramExtension

operations = [TrigramExtension()]

【讨论】:

  • 我已经安装了pg_trgm;否则,三元组搜索工作。我只是不知道如何将 2 个字段组合成一个表达式
猜你喜欢
  • 2018-03-23
  • 2015-09-09
  • 2020-11-02
  • 2018-01-13
  • 1970-01-01
  • 2014-12-25
  • 2020-08-22
  • 2012-05-03
  • 2021-04-03
相关资源
最近更新 更多