所以我正在尝试在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的一些教程/文档中的说明,我在/config/initializers
下创建了一个名为geography.rb
的初始值设定项文件,其中包含以下内容。
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将点数据视为地理数据。 基于这个问题,我猜我可能需要调整寄存器调用以匹配我的架构文件,所以我实际上有 4 个寄存器行的副本,涵盖geo_type:"点"/"st_point",并且geographic: true.
的存在/不存在没有帮助。
我错过了什么/误解/做错了什么? 我猜这是一个配置问题,只是不知道它是什么,不幸的是,我已经达到了我可以根据文档和教程弄清楚的极限 - 唉 - 已经有点过时了。
所以在做了一些额外的实验之后,我终于意外地找到了解决方案。
事实证明我不需要配置块。 没有它,正确的默认值就会加载。 重新阅读,显然文档试图涵盖另一个用例,我只是没有像我希望的那样清楚地理解它。