[英]Django Aggregate Min Max Dynamic Ranges
我有以下模型:
class Claim:
amount = models.PositiveIntegerField()
我正在尝试创建以数量范围是动态的方式动态发送响应的 API。
例如,我的最低索赔金额为 100,最高金额为 1000 我想以这种方式显示 JSON:
{
"100-150": 2,
"150-250": 3,
"250-400": 1,
"400-500": 5,
"above_500": 12
}
假设我的数据范围在 1 到 2000 之间,我尝试这样做,但如果我的最小数量在 10000 到 100000 之间,这将毫无用处。
d = Claim.objects.aggregate(upto_500=Count('pk', filter=Q(amount__lte=500)),
above_500__below_1000=Count('pk', filter=Q(amount__range=[501, 999])),
above_1000__below_2000=Count('pk', filter=Q(amount__range=[1000, 2000])),
above_2000=Count('pk', filter=Q(amount__gte=2000))
)
知道我们如何以动态方式获取数量范围并将其扔到前端吗?
我想这就是你要找的:
from django.db.models import Max, Min, Count, Q
# Retrieve min and max of amount
claim_min_max = Claim.objects.aggregate(Min("amount"), Max("amount"))
amount_min = claim_min_max["amount__min"]
amount_max = claim_min_max["amount__max"]
step = 100
# Create a list of pairs of size "step"
elements = range(amount_min, amount_max, step)
pairs = []
for i in range(len(elements)):
try:
pairs.append((elements[i], elements[i + 1]))
except IndexError:
break
# Add the last pair until the end
pairs.append(pairs[:-1][1], amount_max)
aggregate_pairs = {
f"from_{_from}_to_{_to}": Count("pk", filter=Q(amount__range=[_from, _to]))
for _from, _to in pairs
}
queryset = Claim.objects.aggregate(**aggregate_pairs)
批量计数元素的动态方法
让单个值充当范围的标识符,然后按该值分组。 当除以步长时,该标识符可以是商。
例如,如果您有值: [121, 131, 170, 215, 390]
,请将其转换为[100, 100, 150, 200, 350]
(假设 step=50)并计算值。
from django.db.models import Count, F, IntegerField
from django.db.models.functions import Cast, Floor
step = 50
# Ignore the min/max logic altogether if you don't care about getting these explicitly
min_value = 100
max_value = 500
claims = Claim.objects.all()
claims = claims.filter(amount__gte=min_value, amount__lt=max_value)
counts = (
claims.annotate(
value=Cast(
Floor(F('amount') / (step * 1.0)) * step,
output_field=IntegerField(),
)
)
.values('value')
.annotate(count=Count('*'))
.values_list('value', 'count')
)
ranges = {}
for value, count in counts:
range_name = f"{value}-{value + step}"
ranges[range_name] = count
ranges[f"<{min_value}"] = Claim.objects.filter(amount__lt=min_value).count()
ranges[f">={max_value}"] = Claim.objects.filter(amount__gte=max_value).count()
from django.db.models import Q
upto_500=Count('pk', filter=Q(amount__lte=500))
above_500__below_1000=Count('pk', filter=Q(amount__range=(501, 999)))
above_1000__below_2000=Count('pk', filter=Q(amount__range=(1000, 2000)))
above_2000=Count('pk', filter=Q(amount__gte=2000))
claim = Claim.objects.annotate(upto_500=upto_500).annotate(above_500__below_1000=above_500__below_1000).annotate(above_1000__below_2000=above_1000__below_2000).annotate(above_2000=above_2000)
print(claim[0].upto_500)
这是小于 500 的计数,依此类推。
现在您可以轻松地从中创建 JSON。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.