Just ex-geodesy student, who become programmer. As hobby... base stuff like coding, playing games and listen to music. Sometimes swimming and skiing.
It's a database wrapper and language integrated query for Elixir
It allows us to write clean, maintainable SQL queries on steroids and write it fast.
Also, it allows to map SQL data into structs, and not only plain data like strings but also GIS data like points or lines.
A geographic information system (GIS) is a system designed to capture, store, manipulate, analyze, manage, and present spatial or geographic data.
It allows us to do all operations listed above with spatial/temporal/geographic data and with proper connections between them it makes "real" physical location on Earth.
It can be and it is used in "spatial" data systems around the world
Storing marketing information? Yes, it is.
Field investigation and analysis? Yep...
Nearest pub with beer? Of course...
Its an OpenSource plugin to PostgreSQL which is adding support for GiS data.
It allows us to save, search, manipulate data in SQL database making it true spatial database management system. And we can do it using just SQL with some additional functions.
Also it supports Multi-dimensional spatial indexing!
defmodule PostGisSample.Mixfile do
defp deps do
[
# ....
{:geo, "~> 3.0", override: true},
{:geo_postgis, "~> 2.0"},
{:topo, "~> 0.1.0"}
]
end
end
defmodule PostGisSample.Repo.Migrations.AddLocationsTable do
use Ecto.Migration
def up do
execute "CREATE EXTENSION IF NOT EXISTS postgis"
create table(:locations) do
add :name, :string
add :latitude, :decimal, precision: 9, scale: 7
add :longitude, :decimal, precision: 9, scale: 7
add :geom, :geometry
end
execute "CREATE INDEX idx_locations_geom ON locations using GIST(geom)"
end
def down do
execute "DROP INDEX idx_locations_geom;"
drop table(:locations)
execute "DROP EXTENSION IF EXISTS postgis"
end
end
def save!(name, longitude, latitude) do
name
|> build_struct(longitude, latitude)
|> PostGisSample.Repo.insert!()
end
defp build_struct(name, long, lat) do
%PostGisSample.Location{
name: name,
longitude: long,
latitude: lat,
geom: %Geo.Point{
coordinates: {long, lat},
srid: 4326
}
}
end
def find_location(long, lat, radius) do
long
|> build_point(lat)
|> build_query(radius)
|> PostGisSample.Repo.one()
end
defp build_point(long, lat) do
%Geo.Point{
coordinates: {long, lat},
srid: 4326
}
end
defp build_query(center, radius) do
import Ecto.Query
from(
locations in PostGisSample.Location,
where:
fragment(
"ST_DWithin(geom::geography, ?, ?)",
^center,
^radius
)
)
end
defmacro in_radius(column, center, radius) do
quote do
fragment("ST_DWithin(?::geography, ?, ?)",
unqote(column),
unqote(center),
unqote(radius))
end
end
def find_location(long, lat, radius) do
long
|> build_point(lat)
|> build_query(radius)
|> PostGisSample.Repo.one()
end
defp build_point(long, lat) do
%Geo.Point{
coordinates: {long, lat},
srid: 4326
}
end
defp build_query(center, radius) do
import Ecto.Query
from(
locations in PostGisSample.Location,
where: in_radius(locations.geom, center, radius)
)
end
def box2d() do
import Ecto.Query
query = from(
l in PostGisSample.Location,
select: %{
box: fragment("ST_AsGeoJSON(ST_Extent(?), 15, 1) AS box", l.geom)
}
)
query
|> PostGisSample.Repo.one()
|> Map.get(:box)
|> Poison.decode!()
end
For example ElasticSearch or SOLR
Check this guy: Topi Tjukanov