Django提供了一个SearchQuery类把查询词转换为一个搜索查询对象。
使用全文搜索的实例,根据查询词出现的频率和它们之间的距离对结果进行排序。
关于全文搜索更多内容,请看Django全文搜索-CSDN博客
相关性排序
编辑views.py,添加以下导入
python
from django.contrib.postgres.search import SearchVector,SearchQuery,SearchRank
找到post_search
python
results = Post.objects.annotate(
search = SearchVector('title','body'),
).filter(search=query)
替换为
python
search_vector = SearchVector('title','body')
search_query = SearchQuery(query)
results = Post.objects.annotate(
search = search_vector,
rank = SearchRank(search_vector,search_query)
).filter(search=search_query).order_by('-rank')
创建一个SearchQuery对象,通过它过滤结果,并使用SearchRank按相关性对结果排序。
- SearchVector:在哪里查询
- SearchQuery:查询词是什么
- SearchRank:如何排序
权重排序
在按相关性排序结果时赋予它们更多权重。
例如,按标题而不是按内容匹配的帖子提供更多相关性。
python
search_vector = SearchVector('title',weight='A') + SearchVector('body',weight='B')
search_query = SearchQuery(query)
results = Post.objects.annotate(
search = search_vector,
rank = SearchRank(search_vector,search_query)
).filter(rank__gte=0.3).order_by('-rank')
使用title和body字段构建的搜索向量应用了不同的权重。
默认权值为D(0.1),C(0.2),B(0.4),A(1.0)
示例对标题的搜索权重为1,对正文的权重为0.4。所以标题匹配讲优先于正文匹配。
对结果进行过滤,只显示排名高于0.3的结果。
最终查询方法代码示例
python
def post_search(request):
form = SearchForm()
query = None
results = []
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
query = form.cleaned_data['query']
search_vector = SearchVector('title',weight='A') + SearchVector('body',weight='B')
search_query = SearchQuery(query)
results = Post.objects.annotate(
search = search_vector,
rank = SearchRank(search_vector,search_query)
).filter(rank__gte=0.3).order_by('-rank')
template = "blog/post/search.html"
context={
'form':form,
'query':query,
'results':results,
}
return render(request,template,context)
关于全文搜索的表单类,模版和路径的构建,请查看Django全文搜索-CSDN博客