geo 查询从 ruby 复制到 Ecto Elixir

geo Query replicating from ruby to Ecto Elixir

在 Ruby 中我有这个函数 query.by_distance 其中 by_distance 类似于

  def_dataset_method(:by_distance) do |from, meters|
    point = Geocoding.as_point(from)
    query = "ST_DWithin(location, ST_SetSRID(ST_Point(?, ?), 4326)::geography, ?)"
    where(query, point.lng, point.lat, meters)
  end

在 ruby 端点用户传递 2 个值,它们是 is_near_to,主要是城市或国家的名称。Geecoding 通过它获得积分和 2值为 within_distance,其中 meters 用于在此 distance.

内获取摄像头

以上发生在Ruby。

在 Elixir 中复制它的方法是

  def by_distance(query, is_near_to, within_distance) do
    [%{"lat" => lat, "lng" => lng}] = fetch(is_near_to)
    latitude = lat
    longitude = lng
    query
    |> where([cam], st_dwithin(cam.location, st_set_srid(st_point_from_text(^"#{latitude},#{longitude}"), 4326), ^within_distance))
  end

为了获得纬度和经度,我正在做一些

defmodule EvercamMedia.Geocode do

  def fetch(address) do
    response = HTTPotion.get "http://maps.googleapis.com/maps/api/geocode/json?address=#{URI.encode(address)}&sensor=false"

    {:ok, results} = Poison.decode response.body

    get_in(results, ["results", Access.all(), "geometry", "location"])
  end
end

现在我有相同的场景。我有两个值 is_near_towithin_distance。但是我完全不知道这一点,我如何在查询中复制与我们在项目中使用 geo 相同的东西,根据文档,这显然是可能的,但我不知道如何去做。

这是我正在开发的应用程序的一部分,我相信它可以满足您的需求,它使用片段将 ST_distance_sphere 调用直接传递给 postgis。

使用库 https://github.com/bryanjos/geo 和 postgis

模型中

def near_by(query, point, distance) do
  from place in query,
  where: fragment("ST_distance_sphere(?,?)", place.location, ^point) >= ^distance,
  order_by: fragment("ST_distance_sphere(?,?)", place.location, ^point),
  select: {place, fragment("ST_distance_sphere(?,?)", place.location, ^point)}
end

控制器

def near_by(conn, %{"latitude" => latitude, "longitude" => longitude, "distance" => distance}) do
  point = %Geo.Point{coordinates: {String.to_float(latitude), String.to_float(longitude)}, srid: 4326}
  places = Place
  |> Place.near_by(point, String.to_float(distance))
  |> Repo.all
  render(conn, "near_by.json", places: places)
end

视图中

def render("near_by_place.json", %{place: place}) do
  { place, distance } = place
  {lat, lon} = place.location.coordinates
  %{id: place.id,
    name: place.name,
    latitude: lat,
    longitude: lon,
    distance: distance}
end