Как отфильтровать / уменьшить QuerySet для каждой n-й строки? - PullRequest
1 голос
/ 07 июня 2019

Я храню данные временных рядов от ряда датчиков в базе данных MySQL.Каждый датчик связан с устройством, и каждое устройство может иметь несколько датчиков.

Датчики опрашивают каждые 10 секунд, поэтому в течение длительных периодов (день / неделя / месяц / год) выбор излишне большого набора данных становится проблематичным.

Я хотел бы пересчитать QuerySet перед оценкой, чтобы он выбирал только каждую n-ю строку.Возможно ли это?

Если нет, могу ли я использовать более разумный подход?Я полагаю, я мог бы найти предложение where, которое соответствует 1 / n из возможных значений для микросекунд временной метки?

device_name = request.GET['device']
   device = Datalogger.objects.get(device_name=device_name)

   sensors = Sensor.objects.filter(datalogger=device).order_by('pk').select_related('type')
   sensor_models = sensors.values_list('type', flat=True)  # get all models of sensor used by this controller
   sensor_datum_types = list(SensorModelDatumType.objects.filter(sensor__in=sensor_models).order_by('sensor',
                                                                                                    'datum_type'))  # get all datatypes relating to all models of sensor used

# assign each trace (sensor/datum_type combination) an indice for the tuples (zero is used for time/x-axis)
   bulk_queryset = SensorDatum.objects.filter(sensor__datalogger__device_name=device_name,
                                              timestamp__gte=get_filter_start_time(request),
                                              timestamp__lte=get_filter_end_time(request))
   chart_traces = []
   chart_trace_indices = {}
   chart_trace_data = [None]
   chart_trace_queryset = SensorDatum.objects.none()
   next_free_idx = 1
   for sensor in sensors:
       for datum_type in sensor_datum_types:
           if datum_type.sensor == sensor.type:
               chart_trace_name = get_chart_trace_name(sensor.sensor_name, datum_type.datum_type.description)
               chart_traces.append({'sensor': sensor.sensor_name, 'datum_type': datum_type.datum_type.description,
                                    'chart_trace_name': chart_trace_name})
               chart_trace_indices.update({chart_trace_name: next_free_idx})
               chart_trace_queryset = chart_trace_queryset | bulk_queryset.filter(sensor_id=sensor.id,
                                                                                  type_id=datum_type.datum_type.id)
               next_free_idx += 1

   # process data into timestamp-grouped tuples accessible by chart_trace_index ([0] is timestamp)
   raw_data = list(chart_trace_queryset.order_by('timestamp', 'sensor_id', 'type_id'))
   row_count = len(raw_data)

1 Ответ

0 голосов
/ 07 июня 2019

Возможно, вы могли бы использовать .annotate() и модуль для извлечения только каждой N-й строки. Я использую этот ответ для справки.

Foo.objects.annotate(idmod4=F('id') % 4).filter(idmod4=0)

Это должно возвращать примерно каждую 4-ую строку, хотя, если вы используете и некоторые другие фильтры, тогда вы можете не получить точную подвыборку, фильтр может исключить группу строк, которые бы соответствовали модулю, так что вам не повезло, что сканер, по которому вы фильтруете, не имеет столько идентификаторов, сколько кратно 4. Хотя вы упомянули, что вы генерируете много строк, и для подвыборки этого может быть достаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...