最近、私は自分の目標のためにジオコーダーを作成することになりましたAriadna
カットの下には、私がそれをした理由と彼が何ができるかについての物語があります。
この記事には、Goの1行のコードは含まれません。 しかし、ジオコーダーの動作と私が遭遇した問題の完全な説明があります。 コードはgithubで見ることができます。
背景
私はキルギスタンのビシュケクのタクシーサービスの1つで働いています。 注文のより最適な分布のために、住所の座標の位置を最適化することにしました。
持っていないもの:
- 完全なYandex、Googleまたは2Gisカード
- GPSデータの信頼
私たちは何を持っています:
- 非常に混合された入力データ
- Openstreetmap
- 座標を持つ独自の累積アドレスベース
ユーザーは何を入力できますか?
ユーザーはさまざまな形式でアドレスを入力できます。
- ストリートハウス
- 交差点
- 機関名
- ポイント名
- 団地
- 小地区通りの家
そして、そのようなオプションはたくさんあります。例えば
キエフスカヤ28
キエフソビエト
5-42
5ソ連の小地区42
TSUM
アショット近くのカフェ
障壁
などなど
問題の声明
入力データを受け入れて座標を与えることができるジオコーダーを作成します
検索言語はロシア語のみです。
そんな人生に来る方法
自転車を作る前に、私はすでに存在する解決策を見つけることにしました。
だった:
私たちが持っていた指名に適さないもの:
- 単独で折りたたまれています
- php + cで作成(これはphpが悪いためではなく、このツールのためだけにApacheとphpがあるためです)
- Postgresqlストアドプロシージャの複雑なロジック
Peliasが気に入った点:
- 多くのジオデータベースで動作可能
- ElasticSearchによって整理された検索
その結果、3つのジオコーダーをすべて放棄し、いくつかの理由でツールを作成することにしました。
- OSMのデータを把握し、検索する必要があるデータのみをインポートしたい
- インデックスを作成する前にジオデータを処理できます
- 私はjavascriptとnode.jsが好きではないので、Peliasに基づいて検索をしたい
設計
次のアルゴリズムが定められました。
- まず、大規模な集落(都市、首都、村、住宅団地)のジオメトリを取得します
- 考えられるすべての住所をアンロードし、それらを目的の住宅団地、都市、その他の地域に関連付けて、目的の値を設定します
- すべての道路をアンロードする
- 横断歩道を探しています
- すべてをインデックスに入れる
- 探している
実装には、 pbf2json 、 golang-geoなど、ジオデータ処理用のその他の多くのプロジェクトを考えて 、Goを選択しました。 また、そのスキルを揺るがしたかったです。
実装
osmを使用したデータの受信と解析により、私はそれをある程度理解しました。 住宅地の場合、フィルタリングに場所=都市、場所=村、場所=郊外、場所=町、場所=近所のタグを使用します。 住所、建物を取得するには、addr:street + addr:housenumber、amenity、shop、addr:housenumber
すべての道路は、高速道路タグを使用して取得できます。
ロシア語の英語名の検索には困難がありました。 私がこれを解決しようとした方法:
- ロシア語への簡単な自動音訳。 結果はばかげていて、正しくありませんでした。 データ変換の例は次のとおりです。CityHouse-> Citi House
- このように変換してみましょう。 単語の転写を受け取り、すでに文字変換します。 アドレナリンラッシュ->エルデナリンラッシュのようなものになりました。 まずまずですが、アドレナリンラッシュなどのロシア語のアクセントが必要です。
- そのようなメカニズムが登場しました。 置換辞書を使用して、すべてのデータを自動的に音訳します。 それでも、単純で愚かな音訳は合理的に機能します。 辞書は、データを何度か実行することで、原則としてすばやく埋められました。
この時点で整理されたため、次のデータをすでに受信しています。
- 正規化され、ロシア語に縮小
- 住所は、国、市、村または町、小区域または住宅団地、通り、家の形式で与えられます
クエストの次の部分は、道路の交差点を見つけることです。 速くし、実装を非常に遅くしました。複雑さはO(n ^ 2)です。 一時的な出口として、交差点を見つけるための適切なアルゴリズムが見つかるまで、Postgres + postgisを使用して交差点を見つけます。
その結果、ElasticSearchにデータを配置する優れたosmデータパーサーが作成されます。 シンプルネームインポーターを取得したのは誰ですか
自動化する
elastixerchでインデックスを絶えずポンピングおよび作成することにすぐに飽きてしまうという事実を考慮して、アップデータコンポーネントが登場しました。 JSON形式の自動構成もありました。
ファイルをダウンロードしてエラスティック検索にインポートするプロセスは自動化されました。 さらに、エイリアスのおかげで、ダウンタイムなしでelasticixerのデータを更新できるようになりました。
仕組み:
- アップデータダウンロードファイル
- 構成からインデックスの現在のバージョンを認識します
- バージョンをインクリメントし、新しいインデックスを作成します
- データを入力します
- エイリアスを変更する
- 古いインデックスを削除します
これからそのような恩恵を受けました:
- 設定を書いています
- ./ariadna updateを起動します
- コーヒーを飲みに行きましょう
- 既製のカスタマイズされたインデックスを取得します。
また、便宜上、地図と検索機能を備えたシンプルなWebインターフェイスを台無しにしました。
自動データ補充
OSMに加えて、注文を処理する多くのドライバーとオペレーターがまだいます。
したがって、名前と座標があります
次のスキームが作成されました。
- ドライバーのトラックは、drivers_dataインデックスに保存されます
- OSMデータはosm_dataインデックスに保存されます
- それらは、アドレスが検索されるエイリアスアドレスを介して結合されます
200メートルを超える特定の座標にエラーがある場合、ドライバーからのデータが入力されます。
合計
結果は次のことができるジオコーダーです:
- 同義語で座標を検索します。 例:ShVK-ChampagneVinKombinat
- 特定の半径内の住所を検索できる(たとえば、私は自分が市内中心部から30 kmの住所を検索した)
- 機関名で検索(例:アショット近くのカフェ)
- 交差点を検索
- 団地と団地の住所を検索する
- 逆ジオコーディング
- ドライバーからの新しいデータで自動的に補充されます
3つのコンポーネントで構成されます。
- データインポーター
- データアップデーター
- Webインターフェース
短所
- キルギスタンのみでテスト済み
- デモなし
- すべてのアドレッシングスキームのサポートなし
したがって、誰かが他の国や都市での良い検索のためにそれを完成させるのを手伝ってくれることを願っています。
誰かがプロジェクトが面白いと思ったら、批判、リクエストのプール、githubの問題、一般的なフィードバックに反対しません。