这可以减少为单个查询吗?
Can this be reduced to a single query?
我有一个带有字段 position = PositiveIntegerField(unique=True)
的模型。给定此模型的一个实例,我想获得具有下一个最高位置的实例(受某些过滤器的约束)。如果这个实例是位置最高的那个,我想环绕到 0 和 return 位置最低的实例;如果这个实例是唯一的,我想 return 本身。
这是我的代码:
count = Player.objects.count()
return Player.objects.filter(game_id=self.game_id, is_alive=True).annotate(
relative_position=(F('position') - self.position - 1 + count) % count
).order_by('relative_position')[:1].get()
(+ count
的原因是因为负数对正数的模在SQL中是负数。)
这需要两次数据库查询。我怀疑使用 annotate
和 Count
仅在一个查询中就可以做到这一点,但我还没有弄清楚如何将这样的查询放在一起。可以做到吗?如果可以,怎么做?
不一定总是一个查询,但它可能胜过 2 个查询和注释:
players = Player.objects.filter(game_id=self.game_id, is_alive=True).order_by('position')
try:
return players.filter(position__lt=self.position)[0]
except IndexError:
return players.last()
我发现条件查询表达式是 Django 1.8 中的一个东西,这意味着我可以放弃模运算并这样做:
return Player.objects.filter(game_id=self.game_id, is_alive=True).order_by(
Case(When(position__gt=self.position, then=Value(0)), default=Value(1)),
'position'
)[:1].get()
我有一个带有字段 position = PositiveIntegerField(unique=True)
的模型。给定此模型的一个实例,我想获得具有下一个最高位置的实例(受某些过滤器的约束)。如果这个实例是位置最高的那个,我想环绕到 0 和 return 位置最低的实例;如果这个实例是唯一的,我想 return 本身。
这是我的代码:
count = Player.objects.count()
return Player.objects.filter(game_id=self.game_id, is_alive=True).annotate(
relative_position=(F('position') - self.position - 1 + count) % count
).order_by('relative_position')[:1].get()
(+ count
的原因是因为负数对正数的模在SQL中是负数。)
这需要两次数据库查询。我怀疑使用 annotate
和 Count
仅在一个查询中就可以做到这一点,但我还没有弄清楚如何将这样的查询放在一起。可以做到吗?如果可以,怎么做?
不一定总是一个查询,但它可能胜过 2 个查询和注释:
players = Player.objects.filter(game_id=self.game_id, is_alive=True).order_by('position')
try:
return players.filter(position__lt=self.position)[0]
except IndexError:
return players.last()
我发现条件查询表达式是 Django 1.8 中的一个东西,这意味着我可以放弃模运算并这样做:
return Player.objects.filter(game_id=self.game_id, is_alive=True).order_by(
Case(When(position__gt=self.position, then=Value(0)), default=Value(1)),
'position'
)[:1].get()