Reputation: 99
I want to customize the rank results given by SearchRank by giving more weights to some courses based on the value of a field in the Course Model.
I want use the rank given by SearchRank:
vector=SearchVector('title', weight='A')+SearchVector('full_description', weight='B')
query = SearchQuery(search)
courses=Course.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by('-rank')
and Create a new one:
rank2=[course.rank*2 if course.field1==Value1 else course.rank for course in courses]
And use this new rank to order the courses:
courses.annotate(rank2=rank2).order_by('-rank2')
But this gives me the error:
AttributeError: 'list' object has no attribute 'resolve_expression
I also tried to modify the original rank before reordering again, but it seems to use the initial rank values vs. the new ones:
def adjust_rank(courses):
courses_temp=courses
for course in courses_temp:
if course.field1==Value1:
course.rank=course.rank*2
return courses_temp
courses2=adjust_rank(courses).order_by('-rank')
What is the best way to do this ?
In the Postgresql documentation, I can read:
You can write your own ranking functions and/or combine their results with additional factors to fit your specific needs.
But I have no idea on how to do that.
I am using Django 1.11.1 and python 2.7.13
Upvotes: 0
Views: 1426
Reputation: 6122
You can do it with one query, using conditional expression:
from django.db.models import Case, When, F
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
vector = SearchVector('title', weight='A') + SearchVector('full_description', weight='B')
query = SearchQuery(search)
rank = SearchRank(vector, query)
Course.objects.annotate(
rank0=rank,
rank1=Case(When(field1='Value1', then='rank0'), default=0.0),
rank2=F('rank0') + F('rank1')
).filter(rank0__gte=0.3).order_by(-'rank2')
Upvotes: 3