因此,我正在尝试在Rails中为项目加速基于位置的编程。总之,我的数据库数据似乎是正确的,但我无法获得rails内存逻辑以获得正确的结果。
我在我的数据库中创建了一个lonlat列...
add_column :bars, :lonlat, :st_point, geographic: true
哪个已在我的架构文件中创建了相应的条目...
t.geography "lonlat", limit: {:srid=>4326, :type=>"st_point", :geographic=>true}
当我运行像Bar.where("ST_Distance(lonlat, 'Point(0,0)') < 10000")
这样的查询时,我会得到理智的结果。 (我没有检查准确性,只是粗略的理智)。例如,如果我运行Bar.where("ST_Distance(lonlat, 'Point(0,0)') < 100").count
,我会返回1 - 恰好位于相关点的单个记录。
但如果我加载记录......
b1 = Bar.first
b2 = Bar.second
b1.lonlat.distance(b2.lonlat)
# Result is around or below 0.009
结果是错误的。事实上,这两点相距约3000英尺,快速检查上面的计数查询表明数据库至少可以理解这一点。
所以,据我所知,问题只有在我将点数加载到内存中之后。
根据RGeo的一些教程/文档中的说明,我在geography.rb
下创建了一个名为/config/initializers
的初始化文件,其中包含以下内容。
RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config|
# By default, use the GEOS implementation for spatial columns.
config.default = RGeo::Geos.factory_generator
# But use a geographic implementation for point columns.
config.register(RGeo::Geographic.spherical_factory(srid: 4326), geo_type: "point")
# Also tried the additional calls to try and get the declaration to match my schema file's column definition
config.register(RGeo::Geographic.spherical_factory(srid: 4326), geo_type: "point", geographic: true)
config.register(RGeo::Geographic.spherical_factory(srid: 4326), geo_type: "st_point")
config.register(RGeo::Geographic.spherical_factory(srid: 4326), geo_type: "st_point", geographic: true)
end
我的理解是这个代码 - 特别是第二个调用config.register
,应该告诉RGeo将点数据视为地理数据。基于this问题,我猜我可能需要调整寄存器调用以匹配我的模式文件,所以我实际上有4个寄存器行副本,覆盖geo_type:“point”/“st_point”,以及是否存在geographic: true.
没有帮助。
我错过了什么/误解/做错了什么?我猜它是一个配置问题,只是不知道它是什么,不幸的是我已经达到了我可以根据文档和教程找出的限制 - 唉 - 已经过时了。
所以经过一些额外的实验,我终于意外地找到了解决方案。
结果我不需要配置块。没有它,正确的默认值被加载。重新阅读,显然文档试图涵盖另一个用例,我只是没有像我希望的那样清楚地理解它。