Merge branch 'setop/mobilizon-fix-search-perf' into 'main'

Add spatial indexes on address table

Closes #1047

See merge request framasoft/mobilizon!1206
This commit is contained in:
Thomas Citharel 2022-04-07 10:01:45 +00:00
commit f788839665
5 changed files with 32 additions and 4 deletions

View file

@ -32,6 +32,7 @@ variables:
APP_VERSION: "${CI_COMMIT_REF_NAME}"
APP_ASSET: "${CI_PROJECT_NAME}_${CI_COMMIT_REF_NAME}_${ARCH}.tar.gz"
CYPRESS_INSTALL_BINARY: 0
HEX_MIRROR: https://cdn.jsdelivr.net/hex
cache:
key: "${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA}"

View file

@ -1330,12 +1330,15 @@ defmodule Mobilizon.Events do
defp events_for_location(query, %{location: location, radius: radius})
when is_valid_string(location) and not is_nil(radius) do
with {lon, lat} <- Geohax.decode(location),
point <- Geo.WKT.decode!("SRID=4326;POINT(#{lon} #{lat})") do
point <- Geo.WKT.decode!("SRID=4326;POINT(#{lon} #{lat})"),
{{x_min, y_min}, {x_max, y_max}} <- search_box({lon, lat}, radius) do
query
|> join(:inner, [q], a in Address, on: a.id == q.physical_address_id, as: :address)
|> where(
[q],
st_dwithin_in_meters(^point, as(:address).geom, ^(radius * 1000))
[q, ..., a],
st_x(a.geom) > ^x_min and st_x(a.geom) < ^x_max and
st_y(a.geom) > ^y_min and st_y(a.geom) < ^y_max and
st_dwithin_in_meters(^point, a.geom, ^(radius * 1000))
)
else
_ -> query
@ -1344,6 +1347,15 @@ defmodule Mobilizon.Events do
defp events_for_location(query, _args), do: query
@spec search_box({float(), float()}, float()) :: {{float, float}, {float, float}}
defp search_box({lon0, lat0}, radius) do
km_per_lat_deg = 111.195
lat_amp = radius / km_per_lat_deg
km_per_lon_deg_at_lat = Haversine.distance({0.0, lat0}, {1.0, lat0}) / 1000
lon_amp = radius / km_per_lon_deg_at_lat
{{lon0 - lon_amp, lat0 - lat_amp}, {lon0 + lon_amp, lat0 + lat_amp}}
end
@spec filter_online(Ecto.Query.t(), map()) :: Ecto.Query.t()
defp filter_online(query, %{type: :online}), do: is_online_fragment(query, true)

View file

@ -218,7 +218,8 @@ defmodule Mobilizon.Mixfile do
{:mox, "~> 1.0", only: :test},
{:junit_formatter, "~> 3.1", only: [:test]},
{:sobelow, "~> 0.8", only: [:dev, :test]},
{:doctor, "~> 0.18.0", only: :dev}
{:doctor, "~> 0.18.0", only: :dev},
{:haversine, "~> 0.1.0"}
] ++ oauth_deps()
end

View file

@ -64,6 +64,7 @@
"guardian_db": {:hex, :guardian_db, "2.1.0", "ec95a9d99cdd1e550555d09a7bb4a340d8887aad0697f594590c2fd74be02426", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:guardian, "~> 1.0 or ~> 2.0", [hex: :guardian, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "f8e7d543ac92c395f3a7fd5acbe6829faeade57d688f7562e2f0fca8f94a0d70"},
"guardian_phoenix": {:hex, :guardian_phoenix, "2.0.1", "89a817265af09a6ddf7cb1e77f17ffca90cea2db10ff888375ef34502b2731b1", [:mix], [{:guardian, "~> 2.0", [hex: :guardian, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "21f439246715192b231f228680465d1ed5fbdf01555a4a3b17165532f5f9a08c"},
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"haversine": {:hex, :haversine, "0.1.0", "14240e90dae07c9459f538d12a811492f655d95fc68f999403503b4f6c4ec522", [:mix], [], "hexpm", "54dc48e895bc18a59437a37026c873634e17b648a64cb87bfafb96f64d607060"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"http_signatures": {:hex, :http_signatures, "0.1.1", "ca7ebc1b61542b163644c8c3b1f0e0f41037d35f2395940d3c6c7deceab41fd8", [:mix], [], "hexpm", "cc3b8a007322cc7b624c0c15eec49ee58ac977254ff529a3c482f681465942a3"},
"httpoison": {:hex, :httpoison, "1.8.1", "df030d96de89dad2e9983f92b0c506a642d4b1f4a819c96ff77d12796189c63e", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "35156a6d678d6d516b9229e208942c405cf21232edd632327ecfaf4fd03e79e0"},

View file

@ -0,0 +1,13 @@
defmodule Mobilizon.Storage.Repo.Migrations.AddIndexesToAddresses do
use Ecto.Migration
def up do
create_if_not_exists(index("addresses", ["st_x(geom)"], name: "idx_addresses_geom_x"))
create_if_not_exists(index("addresses", ["st_y(geom)"], name: "idx_addresses_geom_y"))
end
def down do
drop_if_exists(index("addresses", ["st_x(geom)"], name: "idx_addresses_geom_x"))
drop_if_exists(index("addresses", ["st_y(geom)"], name: "idx_addresses_geom_y"))
end
end