【发布时间】:2020-11-04 11:19:39
【问题描述】:
我正在使用仪表板来显示测量结果的图表。我很难使用 Rails (6) 高效/快速地处理这些数据。
它的 5 个图表(温度、湿度..)都显示来自相同时间跨度的数据,在每个图表中都是平均值、最小值和最大值。所以页面上总共有 15 个数据集。
每个测量(记录)都有五列(温度、湿度..),具有不同的测量读数。图表的测量数量可以在 +- 3000 条记录到 100.000 条以上之间变化。这些测量按月分组。然后计算最小、最大和平均数据集。所以这 15 个数据集都是基于相同的记录。
我的想法是从数据库中加载一次测量并对其进行计算。所以我不必为每个数据集查询数据。从数据库中查询时,我使用 Groupdate gem(https://github.com/ankane/groupdate) 按月快速分组测量。然后我可以每月平均,最小值和最大值。
不幸的是,我每次计算都会收到一个查询。这使页面加载缓慢..知道如何优化数据库的加载测量吗?之后我可以专注于重构代码。
def dashboard_device
@device = Device.find(params[:id])
@last_measurement = @device.measurements.last
@weather_forecast_location = @device.sublocation.location
start_date = Date.parse('1-1-2020')
end_date = Date.parse('31-12-2020')
selected_measurements = @device.measurements.select(:measurement_date, :moisture, :temperature, :dielectricity, :conductivity, :salinity).group_by_month(:measurement_date, range: start_date..end_date, format: '%B')
@moisture = selected_measurements.average(:moisture).compact
@moisture_max = selected_measurements.maximum(:moisture).compact
@moisture_min = selected_measurements.minimum(:moisture).compact
@temperature = selected_measurements.average(:temperature).compact
@temperature_max = selected_measurements.maximum(:temperature).compact
@temperature_min = selected_measurements.minimum(:temperature).compact
@dielectricity = selected_measurements.average(:dielectricity).compact
@dielectricity_max = selected_measurements.maximum(:dielectricity).compact
@dielectricity_min = selected_measurements.minimum(:dielectricity).compact
@conductivity = selected_measurements.average(:conductivity).compact
@conductivity_max = selected_measurements.maximum(:conductivity).compact
@conductivity_min = selected_measurements.minimum(:conductivity).compact
@salinity = selected_measurements.average(:salinity).compact
@salinity_max = selected_measurements.maximum(:salinity).compact
@salinity_min = selected_measurements.minimum(:salinity).compact
render 'dashboard'
end
更新
使用 pluck 似乎有效,但不幸的是我没有得到数据对应的月份。
将控制器更改为
selected_measurements = @device.measurements.select(:measurement_date, :moisture, :temperature, :dielectricity, :conductivity, :salinity).group_by_month(:measurement_date, range: start_date..end_date, format: '%B')
result = selected_measurements.select('MAX(moisture)', 'AVG(moisture)', 'MIN(moisture)')
似乎快到了,但它给出了一个错误:
PG::GroupingError: ERROR: column "measurements.measurement_date" must appear in the GROUP BY clause or be used in an aggregate function
【问题讨论】:
-
您应该在数据库中选择聚合,而不是在 Ruby 中进行数字运算。您可以选择带有字符串
.select('AVG(moisture) AS avg_moisure')的聚合。或者使用 ArelMeasurement.arel_table[:moisture].average.as('avg_moisure')。 -
如果您经常查询相同的聚合,请创建一个 SQL 视图或包含通过运行 cron 选项卡生成的每月聚合的表。
-
这是
group_by_month来自某个宝石吗? -
是的,它是 Groupdate gem (github.com/ankane/groupdate)
标签: ruby-on-rails ruby postgresql