Django SearchQuery与SearchRank多词查询单词匹配无结果问题
多词查询时Django PostgreSQL SearchRank返回0的问题解决
问题描述
我用Django结合PostgreSQL的SearchVector、SearchQuery和SearchRank实现文章搜索,伪代码如下:
from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank from .models import Article vector = SearchVector('title', weight='A') query = SearchQuery(value) results = Article.objects.annotate(rank=SearchRank(vector, query, cover_density=True)).order_by('-rank') for r in results: print(r.rank, r.name)
单独搜索“computer”时,含该词的文章排名为1,符合预期;但搜索“fast computer”这类多词时,所有结果排名均为0。根据文档,SearchQuery默认search_type='plain'会将术语视为独立关键词,却无法匹配含“computer”的文章,移除cover_density=True后结果依旧。需要实现多词查询时单个单词也能匹配的效果。
解决方法
感谢@gitaarik的指引,已找到两种可行方案:
方法A:使用RAW搜索类型
将查询词格式化为RAW搜索字符串,设置search_type='raw':
query_split = value.split(' ') search_string = ' | '.join([f"'{q}'" for q in query_split]) vector = SearchVector('title', weight='A') query = SearchQuery(search_string, search_type='raw') results = Article.objects.annotate(rank=SearchRank(vector, query, cover_density=True)).order_by('-rank')
方法B:组合多个SearchQuery对象
为每个单词创建独立的SearchQuery对象,用|位运算符组合:
import re import functools query_cleaned = re.sub(' +', ' ', value) # 移除多余空格 query_split = query_cleaned.split(' ') queries = [SearchQuery(query) for query in query_split] queries_combined = functools.reduce(lambda x, y: x | y, queries) results = Article.objects.annotate(rank=SearchRank(vector, queries_combined, cover_density=True)).order_by('-rank')
目前暂未确定两种方法的优劣,但均可正常实现需求。
内容的提问来源于stack exchange,提问作者Alvaro Bataller
相关产品推荐
相关产品推荐

