如果我在一个包含多个关键字(没有引号)的网站上搜索——比如红色汽车——我的期望是,首先应该是包含“红色汽车”的条目,然后是包含两个关键字(但不是按顺序)的条目,然后是包含其中一个关键字的条目。(我相信这是类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.
我看到的黑客是使用Django的析取运算符,但我希望有一些不那么黑客的东西。我也很确定这个黑客不会把精确匹配放在第一位。这里是黑客:
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方面可以实现的)来获得我期望的功能?
最佳答案
感谢@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')