【问题标题】:Matching one or more keywords with Django's Postgres full-text searching使用 Django 的 Postgres 全文搜索匹配一个或多个关键字
【发布时间】:2017-09-20 14:49:46
【问题描述】:

如果我在一个包含多个关键字(且没有引号)的网站上搜索——例如 red car——我的期望是包含“red car”的项目应该排在最前面,然后是包含两个关键字(但不按顺序)的项目,后跟包含其中一个关键字的项目。 (我相信这是类 Lucene 系统中的默认行为,但我已经有一段时间没有使用它们了,所以不能确定。)

我希望 Postgres 全文搜索会自动执行此操作,但我早期的测试表明情况并非如此:

## ASSUME: items in database: <blue car>, <green car>, <red truck>

keywords = "red car"
items = ForSaleItem.objects.filter(name__search=keywords)

## RESULT: items is empty/None, whereas it should have each of 
##         the items since one keyword matches.

我看到的 hack 是使用 Django 的析取运算符,但我希望有一些不那么 hacky 的东西。我也很确定这个 hack 不会把完全匹配放在列表的顶部。这是黑客:

from django.db.models import Q
keyword_query = Q()
for keyword in keywords.split(' '):
    keyword_query.add(Q(name__search=keyword), Q.OR)
items = ForSaleItem.objects.filter(keyword_query)

是否有一些我缺少的设置/API(或在 postgres 端可实现的东西)可以获得我期望的功能?

【问题讨论】:

  • 您在寻找多关键词搜索吗? SearchQuery('red') &amp; SearchQuery('car') # red AND carSearchQuery('red') | SearchQuery('car') # red OR car
  • 感谢@Dharshan,您让我重新阅读文档并发现您对SearchQuery('red') | SearchQuery('car') 的建议与SearchRank() 类的组合实现了我正在寻找的东西。

标签: django postgresql full-text-search


【解决方案1】:

感谢@Dharshan 为我指明了正确的方向。正如他或她所指出的,SearchQuery 对象的分离将允许匹配任一关键字。此外,要在列表顶部包含包含两个关键字的项目- 如Django full text search docs 中所述——SearchRank 类可以按如下方式使用:

vector = SearchVector('name')
query = SearchQuery('red') | SearchQuery('car')
items = ForSaleItem.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')

【讨论】:

    【解决方案2】:
    items = ForSaleItem.objects.filter(name__contains=keywords)
    

    【讨论】:

    • 这不起作用;它会导致错误:“不支持查找‘搜索’ CharField 或加入不允许的字段。”
    • 提供您的模型。
    • 我的模型只是ForSaleItem,只有一个字段name=CharField()。请注意,在我的上下文中,__search 不是一个字段;它是来自Django's Full Text Search 功能的内置关键字。看起来 Dharshan 的评论更符合我的要求,所以我会在上面的 cmets 中转发。
    猜你喜欢
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多