轨道中 Json 数组上的地理编码器方法



我正在调用一些第三方API来获取位置

https://localhost:3000/api/v1/locations 

这是以 JSON 格式返回的结果,例如

[{"location_id": 1,"name": "location1" ,"lat": "22.21","long": "-72.54"},{"location_id": 2,"name": "location2","lat": "45.21","long": "-74.21"}]

使用活动记录,我们可以使用地理编码器应用距离过滤器

Location.near([lat, long], 100,units: :km)

但是API响应是json对象,如何使用地理编码器对json对象应用距离过滤器。

不幸的是,地理编码器仅支持ActiveRecord和MongoDB作为存储后端,而不支持JSON。使用ActiveRecord/Mongo地理编码器还可以利用数据库的查询语言(例如.SQL(有效地查找点附近的位置。在您的情况下,您现在基本上有两个选择:

将 JSON 数据存储在活动记录中

您可以将 JSON 数据存储在数据库中,并使用 ActiveRecord 查询数据。https://github.com/alexreisner/geocoder#geospatial-database-queries,在 gem 官方 GitHub 页面上已经有一个很好的文档。

创建类似活动记录的对象

如果您不需要存储来自 API 请求的数据,我建议您使用活动记录,例如易失性数据存储。

class Location
attr_reader :id, :name, :lat, :long
def initialize(id:, name:, lat:, long:)
@id = id
@name = name
@lat = lat
@long = long
end
def to_coordinates
[lat.to_f, long.to_f]
end
class << self
attr_accessor :locations
def from_json(json)
json.each do |location|
locations << new(
id: location[:location_id],
name: location[:name],
lat: location[:lat],
long: location[:long]
)
end
end
def all
locations
end
end
self.locations = []
end
json = [
{"location_id": 1, "name": "location1", "lat": "22.21", "long": "-72.54" },
{"location_id": 2, "name": "location2", "lat": "45.21", "long": "-74.21" }
]
Location.from_json(json)
puts Location.all

现在,我们将"导入"您的 API JSON 响应,并将其作为 Location 中的类属性存储在数组中。这也具有使用对象而不是哈希/JSON的优势。

现在我们可以创建一个near类方法来选择靠近一个点的所有位置。

def near(lat, long, radius: 20, units: :km)
all.select do |location|
Geocoder::Calculations.distance_between(location, [lat, long], units: units) < radius
end
end

这里的缺点是我们需要遍历所有位置并计算距离,因为我们没有 JSON 数据的查询语言。如果性能是一个问题,我建议使用 SQL 数据库(请参阅之前的建议(。

完整示例

require "geocoder"
class Location
attr_reader :id, :name, :lat, :long
def initialize(id:, name:, lat:, long:)
@id = id
@name = name
@lat = lat
@long = long
end
def to_coordinates
[lat.to_f, long.to_f]
end
class << self
attr_accessor :locations
def from_json(json)
json.each do |location|
locations << new(
id: location[:location_id],
name: location[:name],
lat: location[:lat],
long: location[:long]
)
end
end
def all
locations
end
def near(lat, long, radius: 20, units: :km)
all.select do |location|
Geocoder::Calculations.distance_between(location, [lat, long], units: units) < radius
end
end
end
self.locations = []
end
json = [
{"location_id": 1, "name": "location1", "lat": "22.21", "long": "-72.54" },
{"location_id": 2, "name": "location2", "lat": "45.21", "long": "-74.21" }
]
Location.from_json(json)
puts Location.near(45.21, -74.21)

最新更新