add index for weather
This commit is contained in:
parent
c8ee465015
commit
48b8c7de94
4 changed files with 45 additions and 51 deletions
|
|
@ -404,6 +404,34 @@ defmodule Aprsme.Packets do
|
|||
get_packets_for_replay(opts_with_time)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets weather packets for a specific callsign within a time range.
|
||||
This is optimized for weather queries by filtering at the database level.
|
||||
"""
|
||||
@impl true
|
||||
@spec get_weather_packets(String.t(), DateTime.t(), DateTime.t(), map()) :: [struct()]
|
||||
def get_weather_packets(callsign, start_time, end_time, opts \\ %{}) do
|
||||
limit = Map.get(opts, :limit, 500)
|
||||
|
||||
base_query = from(p in Packet, order_by: [asc: p.received_at])
|
||||
|
||||
query =
|
||||
base_query
|
||||
|> filter_by_time(%{start_time: start_time, end_time: end_time})
|
||||
|> filter_by_callsign(%{callsign: callsign})
|
||||
|> filter_weather_packets()
|
||||
|> limit_results(%{limit: limit})
|
||||
|> select_with_virtual_coordinates()
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
|
||||
# Filter for weather packets at the database level
|
||||
defp filter_weather_packets(query) do
|
||||
from p in query,
|
||||
where: p.data_type == "weather" or (p.symbol_table_id == "/" and p.symbol_code == "_")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Retrieves a continuous stream of stored packets for replay in chronological order.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ defmodule Aprsme.PacketsBehaviour do
|
|||
@callback stream_packets_for_replay(map()) :: Enumerable.t()
|
||||
@callback get_packets_for_replay(map()) :: list()
|
||||
@callback get_recent_packets(map()) :: list()
|
||||
@callback get_weather_packets(String.t(), DateTime.t(), DateTime.t(), map()) :: list()
|
||||
@callback clean_old_packets() :: {:ok, non_neg_integer()} | {:error, any()}
|
||||
@callback clean_packets_older_than(pos_integer()) :: {:ok, non_neg_integer()} | {:error, any()}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
|
|||
@moduledoc false
|
||||
use AprsmeWeb, :live_view
|
||||
|
||||
import Jason
|
||||
|
||||
alias Aprsme.Packets
|
||||
alias AprsmeWeb.MapLive.PacketUtils
|
||||
|
||||
|
|
@ -57,59 +55,12 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
|
|||
end
|
||||
|
||||
defp get_weather_history(callsign, start_time, end_time) do
|
||||
opts = %{callsign: callsign, start_time: start_time, end_time: end_time, limit: 1000}
|
||||
|
||||
opts
|
||||
|> Packets.get_packets_for_replay()
|
||||
|> Enum.filter(&PacketUtils.weather_packet?/1)
|
||||
|> Enum.sort_by(& &1.received_at)
|
||||
Packets.get_weather_packets(callsign, start_time, end_time, %{limit: 500})
|
||||
end
|
||||
|
||||
defp default_time_range do
|
||||
now = DateTime.utc_now()
|
||||
{DateTime.add(now, -48 * 3600, :second), now}
|
||||
end
|
||||
|
||||
defp build_temp_chart_svg(history) do
|
||||
data =
|
||||
history
|
||||
|> Enum.map(fn pkt ->
|
||||
[pkt.received_at, pkt.temperature, pkt.dew_point]
|
||||
end)
|
||||
|> Enum.filter(fn [_, t, d] -> not is_nil(t) and not is_nil(d) end)
|
||||
|
||||
if data == [] do
|
||||
"<svg width=\"600\" height=\"300\"><text x=\"50\" y=\"150\">No data</text></svg>"
|
||||
else
|
||||
dataset = Dataset.new(data, ["Time", "Temperature", "Dew Point"])
|
||||
|
||||
dataset
|
||||
|> Plot.new(LinePlot, 600, 300, smoothed: false)
|
||||
|> Plot.titles("Temperature & Dew Point (°F)", nil)
|
||||
|> Plot.axis_labels("Time", "°F")
|
||||
|> Plot.to_svg()
|
||||
end
|
||||
end
|
||||
|
||||
defp build_humidity_chart_svg(history) do
|
||||
data =
|
||||
history
|
||||
|> Enum.map(fn pkt ->
|
||||
[pkt.received_at, pkt.humidity]
|
||||
end)
|
||||
|> Enum.filter(fn [_, h] -> not is_nil(h) end)
|
||||
|
||||
if data == [] do
|
||||
"<svg width=\"600\" height=\"300\"><text x=\"50\" y=\"150\">No data</text></svg>"
|
||||
else
|
||||
dataset = Dataset.new(data, ["Time", "Humidity"])
|
||||
|
||||
dataset
|
||||
|> Plot.new(LinePlot, 600, 300, smoothed: false)
|
||||
|> Plot.titles("Humidity (%)", nil)
|
||||
|> Plot.axis_labels("Time", "%")
|
||||
|> Plot.to_svg()
|
||||
end
|
||||
{DateTime.add(now, -24 * 3600, :second), now}
|
||||
end
|
||||
|
||||
defp calc_dew_point(temp, humidity) when is_number(temp) and is_number(humidity) do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
defmodule Aprsme.Repo.Migrations.AddSenderIndexToPackets do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
# Add index on sender field for efficient callsign filtering
|
||||
create index(:packets, [:sender])
|
||||
|
||||
# Add compound index for sender + received_at for efficient time-based callsign queries
|
||||
create index(:packets, [:sender, :received_at])
|
||||
|
||||
# Add compound index for sender + has_position for weather packet queries
|
||||
create index(:packets, [:sender, :has_position])
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue