Django:将查询结果分解为多个公共元素列表

2024-10-03 04:34:25 发布

您现在位置:Python中文网/ 问答频道 /正文

编辑:添加所有相关模型。补充说明。你知道吗

我必须查询一个名为Data的表,但不是只返回一个列表,而是可能从一个查询返回多个列表。否则,获取queryset结果并将其分解为具有公共SensorParameter字段的对象数组。你知道吗

我有模型数据:

class Data(models.Model):
    sensor_param = models.ForeignKey(SensorParameter, on_delete=models.CASCADE)
    time = models.DateTimeField(db_index=True)
    value = models.FloatField()

模型传感器参数与参数(温度、振动等)和传感器实例(序列号等)有链接:

class SensorParameter(models.Model):
    sensor = models.ForeignKey(Sensor)
    parameter = models.ForeignKey(Parameter)

型号参数(不同传感器可能测量的不同类型参数的容器):

class Parameter(models.Model):
    parameter_name          = models.CharField(max_length=50)
    parameter_unit          = models.CharField(max_length=20, blank=True)

最后是一个将所有其他传感器连接在一起的传感器:

class Sensor(models.Model):
    name            = models.CharField(max_length=50, null=False, blank=True)
    serial_number   = models.CharField(max_length=50)
    sensor_type     = models.ForeignKey(SensorType)

我可以从某个传感器查询某个时间范围内的数据表,方法是执行双重向后查找,并按我希望的方式对结果查询排序,首先按传感器\u参数,然后按时间

sensor = Sensor.objects.get(serial_number=request["data_source"])
range_period = [request['start'], request['end']]
# This is the queryset I have now, though it's not set in stone
data_query = Data.objects.filter(sensor_parameter__sensor=sensor, time__range=range_period).order_by('sensor_parameter', 'time')

这将在一个大列表中列出请求的时间段内请求的传感器的所有数据点。你知道吗

然后,如何将结果列表分解为具有公共SensorParameter字段的多个对象列表(或数组)?你知道吗

示例来自:

queryset_overall_result =
[
    {data_point_1: sensor: X, sensor_parameter: temp, value: 188, time: 00:01}
    {data_point_2: sensor: X, sensor_parameter: vibration, value: 5, time: 00:01}
    {data_point_3: sensor: X, sensor_parameter: temp, value: 185, time: 00:02}
    {data_point_4: sensor: X, sensor_parameter: vibration, value: 6, time: 00:02}
]

收件人:

list_temp =
[
    {data_point_1: sensor: X, sensor_parameter: temp, value: 188, time: 00:01}
    {data_point_3: sensor: X, sensor_parameter: temp, value: 185, time: 00:02}
]

list_vibration = 
[
    {data_point_2: sensor: X, sensor_parameter: vibration, value: 5, time: 00:01}
    {data_point_4: sensor: X, sensor_parameter: vibration, value: 6, time: 00:02}
]

有没有更好的方法来查询数据表,以便在过滤到另一个表时,给我提供按时间排列的多个列表?(传感器参数)

或者使用python将整个queryset结果分解为公共对象元素的多个列表?阵列是理想的,但不确定如何实现这一点。你知道吗

理想情景:

array = 
[
    [
        {data_point_1: sensor: X, sensor_parameter: temp, value: 188, time: 00:01}
        {data_point_3: sensor: X, sensor_parameter: temp, value: 185, time: 00:02}
    ]
,
   [
        {data_point_2: sensor: X, sensor_parameter: vibration, value: 5, time: 00:01}
        {data_point_4: sensor: X, sensor_parameter: vibration, value: 6, time: 00:02}
    ]
]

限制条件:我不知道一个传感器可以测量多少个或哪些传感器参数,根据传感器类型,可以是4到45英寸。我需要尽量减少查询,因为这个查询可能会返回大量数据,并且可能会连续发生多次。DB命中率越低越好。你知道吗


Tags: 列表data参数parametertimevaluemodels传感器
2条回答

使用列表理解并将它们组合成一个列表

sensors = Sensor.objects.all()

array = []

for sensor in sensors:
    list_param = [d for d in data_query if d['sensor_parameter'] == sensor]
    array.append(list_param)

所有的传感器、参数和传感器参数都让我头晕目眩,但我会试试看。如果要按SensorParameter对结果进行分组,默认方法是查询该模型:

qs = (SensorParameter.objects
    .filter(sensor=sensor, data__time__range=range_period)
    .select_related('sensor', 'parameter')
    .distinct()
    .order_by('sensor_parameter'))

由于要访问按时间排序的相关Data对象,因此应发出相应的prefetch_related命令:

from django.db.models import Prefetch
sorted_data_qs = (Data.objects
    .filter(time__range=range_period)
    .order_by('time'))
prefetch = Prefetch('data_set', queryset=sorted_data_qs)
qs = qs.prefetch_related(prefetch) #  using qs from above

只需两个SQL查询,就可以在单个SensorParameter对象中将所有数据按SensorParameter分组。您可以按如下方式访问各个数据行:

for rs in qs:
    for d in rs.data_set.all():
        print(rs.sensor.name, rs.parameter.name, d.value, d.time)

当然,在构造对象时会有一些开销;如果您不需要它们,而只需要数据行,则可以采用另一种方法:

获取满足筛选器要求的所有SensorParameter的列表,然后对所有这些SensorParameter运行单独的查询,获取可以按照最初设想放入列表的词典:

sensor_params = (SensorParameter.objects
    .filter(sensor=sensor, data__time__range=range_period)
    .value_list('id', flat=True))

result_list = []
for sp in sensor_params:
    param_results = list(
        Data.objects
        .filter(sensor_parameter=sp, time__range=range_period)
        .order_by('time')
        .values(
            'sensor_parameter__sensor__name',
            'sensor_parameter__parameter__name',
            'value',
            'time'
        )
    )
    result_list.append(param_results)

这将导致更多的查询(传感器计数加1),但这并不意味着它一定比第一种方法慢(甚至可能更快)。在这里,分组是在数据库中而不是在Python中完成的。你知道吗

相关问题 更多 >