WIP@Railsで地理座標を計算してソート

# 目的

自分のGPS座標と、ある地点の距離郡を計算し、近い順からソートしたい。そこで、いくつかの選択肢を調べてみました。もし、何かご存知ならアドバイスをお願いできませんでしょうか🙇

# PostGIS

[何が違うのか? PostGISと最新版MySQLの GIS機能を徹底比較](http://kenpg.bitbucket.org/blog/201511/29/slides20151127_rev.pdf)によるとMySQLとPostGIS共にGPS座標を計算できるようだ。

## 開発環境

[HomebrewでPostGISをインストール、利用するまで](http://qiita.com/Mitsunori_Tsukada/items/4b62562930f5865bdcf5)

## 本番環境

[Amazon RDS for PostgreSQL](https://aws.amazon.com/jp/rds/postgresql/)によると、AWSはPostGISに対応している。- [PostGIS: Using Geospatial Data with Rails and Django Apps](https://devcenter.heroku.com/articles/postgis) によるとHerokuでも使えそうです。

## 参考情報

- [PostGIS on Rails](http://www.slideshare.net/MattNemenman/post-gis-on-rails-long)
- [PostGISとは？](http://lets.postgresql.jp/documents/tutorial/PostGIS/)
- [PostgreSQLとOracleで緯度経度から半径nメートル内検索を実行してみる。](http://www.infoscoop.org/blogjp/2015/01/21/tutorial_for_geodb/)
- [PostGIS ActiveRecord Adapter](https://github.com/rgeo/activerecord-postgis-adapter)
- [activerecord-postgis-adapterでpostgisを使う](http://openbook4.me/users/1/sections/449) 
- [PostGIS 2.0.0マニュアル日本語訳](http://cse.naro.affrc.go.jp/yellow/pgisman/2.0.0/postgis.html)
- [PostGISのよく使う機能をまとめた](http://d.hatena.ne.jp/EulerDijkstra/20131008/1381190780)

# MySQL

https://kenpg.bitbucket.org/blog/201511/29/slides20151127_rev.pdf によると出来そうで、今回の要件を満たしそうで直ぐに判断できなかったので、後回しとしました。

MySQL5.7のgeometry型を使えば使えるのではという情報を頂きました。geometry型は5.6でも使えるのですが、インデックスが貼れるのは[5.7.4LAB](http://qiita.com/kochizufan/items/a68b30ba74849483f75c)からのようです。

[[Rails]Railsのバージョンを上げたことでspatial_adapterが使用できなくなりました](http://iaseteam.eshizuoka.jp/e1601776.html)を参考に、[activerecord-mysql2spatial-adapter](https://github.com/rgeo/activerecord-mysql2spatial-adapter)を使ってみましたが、なんだかうまく行かずでした。

2年ほど、activerecord-mysql2spatial-adapterも更新が無く、mysql geometry railsなどのクエリで検索してみましたが、あまり情報がヒットせず、gem周りで解決したりするのは、この問題に対してはメジャーな方法ではないのかなと思いました。

そのため、MySQLのコードを発行するプログラムを作成して、この問題に取り組もうと思います。

例えば、このようなマイグレーションを書いても`rake db:migrate`は可能です。

```db/migrate/20170208125740_add_latlong_to_shops.rb
class AddLatlongToShops < ActiveRecord::Migration[5.0]
  def change
    add_column :shops, :latlong, :geometry
  end
end
```

ただ、`db/scheme.rb`がうまく作成できなくなってしまいます。

```db/schema.rb
# Could not dump table "shops" because of following StandardError
#   Unknown type 'geometry' for column 'latlong'
```

ですので、[Could not dump table “data” because of following StandardError](http://stackoverflow.com/questions/35082839/could-not-dump-table-data-because-of-following-standarderror)などを参考に`db/scheme.rb`をやめて`db/structure.sql`を生成するようにしましょう。

```db/structure.sql
--
-- Table structure for table `shops`
--

CREATE TABLE `shops` (
  ...
  `latlong` geometry DEFAULT NULL
  ...
)
```

# MongoDB

MongoDBのGeospatialを使えば出来るかも。

## 参考情報

- [MongoDBの地理空間インデックス・クエリ整理](http://qiita.com/fetaro/items/7f110f18c6dd9ccd0c90)  
- [MongoDBの地理空間のインデックスを試してみる](http://d.hatena.ne.jp/ja9/20101119/1290162711)
- [mongodb - Geospatial Indexing](http://ameblo.jp/principia-ca/entry-11019465138.html)
- [PostGIS vs MongoDB](http://gis.stackexchange.com/questions/9809/best-gis-system-for-high-performance-web-application-postgis-vs-mongodb)
- [Is MongoDB more suitable than PostGIS as backend for geo-enabled Django website?](http://gis.stackexchange.com/questions/111078/is-mongodb-more-suitable-than-postgis-as-backend-for-geo-enabled-django-website)

# ElasticSearch

[Elasticsearchに空間データを突っ込む](http://laughingman7743.hatenablog.com/entry/2015/10/25/235851)

# SQLで距離を計算する

[緯度・経度を用いて距離を算出するSQL](http://qiita.com/naotarou/items/628952e68fef059c6b1a)が参考になりそう。ただ、件数が増えると実行時間が気になります。10000件程度では問題にはならないようでした。

[GeocorderでRailsアプリで簡単に位置情報を扱う](https://dev.9bar.tokyo/rails/geocoder) はとても便利なgemです。[alexreisner/geocoder/lib/geocoder/sql.rb](https://github.com/alexreisner/geocoder/blob/b9179b6667a756c9850e05819526770d14108da2/lib/geocoder/sql.rb) によると上記と同様にSQLで実行しているようです。

geocodedには既知のバグとして [pluckやincludesが正常に動作しない場合](https://github.com/alexreisner/geocoder#activerecord-1)があるようです。

geocodedのSQLはかなり工夫されていて、素早く動作するように設計されているように感じました。

少し運用してみましたが、実際にデータが増えてくるとレスポンス速度が厳しい感じでした。特に近い距離の中に、結構多めの座標が固まってしまい、工夫しているフィルタ部分を抜けて、結構計算が働いてしまうせいかもしれません。

# 距離計算？クラウド

軽く見た感じだと、直ぐには見つけられ無さそうだった。