Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to add support for ST_ClosestPoint #68

Closed
adityasanka opened this issue May 3, 2017 · 4 comments
Closed

Unable to add support for ST_ClosestPoint #68

adityasanka opened this issue May 3, 2017 · 4 comments

Comments

@adityasanka
Copy link

Hi @bryanjos, thanks for the awesome library. I am trying to add a macro to lib/geo/postgis.ex to support ST_ClosestPoint

defmacro st_closestpoint(geometryA, geometryB) do
      quote do: fragment("ST_ClosestPoint(?,?)", unquote(geometryA), unquote(geometryB))
end

I receive the following error while trying to use it with my queries

iex > alias StoreRoom.{Repo, BusStop, Route}
iex > import Ecto.Query
iex > import Geo.PostGIS
iex > home = %Geo.Point{coordinates: {****, ****}, srid: 4326}
iex > query = from r in Route, order_by: st_distance(r.line, ^home), distinct: r.code, limit: 5, select: r
iex > (from r in subquery(query), select: %{pickup: st_closestpoint(r.line, ^home)}) |> Repo.all()
** (Postgrex.Error) ERROR 42883 (undefined_function): function st_closestpoint(geography, unknown) does not exist
[debug] QUERY ERROR db=1.9ms
SELECT ST_ClosestPoint(s0."line",$1) FROM (SELECT DISTINCT ON (r0."code") r0."id" AS "id", r0."org" AS "org", r0."code" AS "code", r0."name" AS "name", r0."line" AS "line", r0."inserted_at" AS "inserted_at", r0."updated_at" AS "updated_at" FROM "routes" AS r0 ORDER BY r0."code", ST_Distance(r0."line",$2) LIMIT 5) AS s0 [%Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}, %Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}]
    (ecto) lib/ecto/adapters/sql.ex:436: Ecto.Adapters.SQL.execute_and_cache/7
    (ecto) lib/ecto/repo/queryable.ex:130: Ecto.Repo.Queryable.execute/5
    (ecto) lib/ecto/repo/queryable.ex:35: Ecto.Repo.Queryable.all/4

I am fairly new to elixir and postgis. Forgive me if this is a trivial mistake. Any guidance would of great help

@bryanjos
Copy link
Contributor

bryanjos commented May 4, 2017

Everything looks right there as far as I can tell. Only thing I can think of is make sure the Postgrex types are set up. Do you get a similar error with st_distance in your query? Also maybe check that you have the postgis extension installed in postgres.

@adityasanka
Copy link
Author

Hi @bryanjos, thank you for the quick reply. The postgis extension is installed and has been enabled for this database.

I verified this by using st_distance

iex(6)> (from r in subquery(query), select: %{distance: st_distance(r.line, ^home)}) |> Repo.all()
[debug] QUERY OK db=249.8ms
SELECT ST_Distance(s0."line",$1) FROM (SELECT DISTINCT ON (r0."code") r0."id" AS "id", r0."org" AS "org", r0."code" AS "code", r0."name" AS "name", r0."line" AS "line", r0."inserted_at" AS "inserted_at", r0."updated_at" AS "updated_at" FROM "routes" AS r0 ORDER BY r0."code", ST_Distance(r0."line",$2) LIMIT 5) AS s0 [%Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}, %Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}]
[%{distance: 1097.178381035}, %{distance: 182.273171646},
 %{distance: 2809.06654445}, %{distance: 171.211571728},
 %{distance: 4322.601294866}]

I have also have the Postgrex types setup using

# define custom postgres types
Postgrex.Types.define(StoreRoom.PostgresTypes,
              [Geo.PostGIS.Extension] ++ Ecto.Adapters.Postgres.extensions(),
              json: Poison)

I went ahead changed the above macro to the following, to check if issue is with "ST_ClosestPoint"

# custom macros
    defmacro st_closestpoint(geometryA, geometryB) do
      quote do: fragment("ST_Distance(?,?)", unquote(geometryA), unquote(geometryB))
    end

Everything worked fine with the following query

iex(9)> (from r in subquery(query), select: %{distance1: st_distance(r.line, ^home), distance2: st_closestpoint(r.line, ^home)}) |> Repo.all()
[debug] QUERY OK db=59.6ms
SELECT ST_Distance(s0."line",$1), ST_Distance(s0."line",$2) FROM (SELECT DISTINCT ON (r0."code") r0."id" AS "id", r0."org" AS "org", r0."code" AS "code", r0."name" AS "name", r0."line" AS "line", r0."inserted_at" AS "inserted_at", r0."updated_at" AS "updated_at" FROM "routes" AS r0 ORDER BY r0."code", ST_Distance(r0."line",$3) LIMIT 5) AS s0 [%Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}, %Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}, %Geo.Point{coordinates: {78.3762, 17.4474}, srid: 4326}]
[%{distance1: 1097.178381035, distance2: 1097.178381035},
 %{distance1: 182.273171646, distance2: 182.273171646},
 %{distance1: 2809.06654445, distance2: 2809.06654445},
 %{distance1: 171.211571728, distance2: 171.211571728},
 %{distance1: 4322.601294866, distance2: 4322.601294866}]

I am unable to figure out the issue with "ST_ClosestPoint". I need to add a few other helper macros as well. Please point me in the right direction. Thanks in advance

@bryanjos
Copy link
Contributor

bryanjos commented May 4, 2017

Sounds like maybe it could be that the function isn't defined in postgis. Try doing a normal sql query with that function and see if you get a similar error

@adityasanka
Copy link
Author

Hi @bryanjos,

I was using the type geography while declaring schema for my tables. ST_ClosestPoint only works with geometry

create table(:routes, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :org, :string
      add :code, :string
      add :name, :string
      add :line, :geometry

      timestamps()
end

Thanks Bryan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants