Django 模型查询最接近的整数匹配
Django model query for the closest integer match
我得到了一些具有不同评分字段值的 Django 模型对象:
puzzles_rating = [0, 123, 245, 398, 412, 445, 556, 654, 875, 1000]
for rating in puzzles_rating:
puzzle = Puzzle(rating=rating)
puzzle.save()
现在,对于 user_rating = 500
,我想要 select 具有最接近评级匹配的拼图。在上面的例子中,它应该是等级为 445 的谜题 #6。
问题是我不能只做:
puzzle = Puzzle.objects.filter(rating__lte=user_rating).order_by('-rating')[0]
因为一般来说,我最接近的匹配评分可能高于目标评分。
有没有方便的方法从两个方向查询最接近的匹配项?
您可以获得两个 Puzzle 对象并在 Python 中进行比较,哪个更接近:
# Note, be sure to check that puzzle_lower and puzzle_higher are not None
puzzle_lower = Puzzle.objects.filter(rating__lte=user_rating).order_by('-rating').first()
puzzle_higher = Puzzle.objects.filter(rating__gte=user_rating).order_by('rating').first()
# Note that in a tie, this chooses the lower rated puzzle
if (puzzle_higher.rating - user_rating) < abs(puzzle_lower.rating - user_rating):
puzzle = puzzle_higher
else:
puzzle = puzzle_lower
您可以使用extra
方法:
puzzle = Puzzle.objects.extra(select={
'abs_diff': 'ABS(`rating` - %s)',
}, select_params=(rating,)).order_by('abs_diff').first()
从 Django 1.8 开始你不需要写 raw SQL,你可以使用 Func
:
from django.db.models import Func, F
puzzle = Puzzle.objects.annotate(abs_diff=Func(F('rating') - rating, function='ABS')).order_by('abs_diff').first()
我得到了一些具有不同评分字段值的 Django 模型对象:
puzzles_rating = [0, 123, 245, 398, 412, 445, 556, 654, 875, 1000]
for rating in puzzles_rating:
puzzle = Puzzle(rating=rating)
puzzle.save()
现在,对于 user_rating = 500
,我想要 select 具有最接近评级匹配的拼图。在上面的例子中,它应该是等级为 445 的谜题 #6。
问题是我不能只做:
puzzle = Puzzle.objects.filter(rating__lte=user_rating).order_by('-rating')[0]
因为一般来说,我最接近的匹配评分可能高于目标评分。
有没有方便的方法从两个方向查询最接近的匹配项?
您可以获得两个 Puzzle 对象并在 Python 中进行比较,哪个更接近:
# Note, be sure to check that puzzle_lower and puzzle_higher are not None
puzzle_lower = Puzzle.objects.filter(rating__lte=user_rating).order_by('-rating').first()
puzzle_higher = Puzzle.objects.filter(rating__gte=user_rating).order_by('rating').first()
# Note that in a tie, this chooses the lower rated puzzle
if (puzzle_higher.rating - user_rating) < abs(puzzle_lower.rating - user_rating):
puzzle = puzzle_higher
else:
puzzle = puzzle_lower
您可以使用extra
方法:
puzzle = Puzzle.objects.extra(select={
'abs_diff': 'ABS(`rating` - %s)',
}, select_params=(rating,)).order_by('abs_diff').first()
从 Django 1.8 开始你不需要写 raw SQL,你可以使用 Func
:
from django.db.models import Func, F
puzzle = Puzzle.objects.annotate(abs_diff=Func(F('rating') - rating, function='ABS')).order_by('abs_diff').first()