geolonia/normalize-japanese-addressesで揺らぎのある住所を簡単に比較する

こんにちは、プロダクト開発部コアグループの井上です。 新決済画面のSmart Checkoutでは住所比較APIを作成して、数ヶ月前から注文者住所と受取先住所の揺らぎを吸収しています。 今回は作成に至った背景やAPIについて紹介します。

背景

makeshopの仕様

makeshop管理画面では注文者と受取人が異なる場合に以下のような仕様があります。

  • 管理画面上で「注文者と異なる送付先」のアラート表示をしている
  • 一部出荷伝票用のCSV出力時に送り主がショップ情報から注文者情報に変わる

課題

住所表記の揺らぎによる誤判定 実際には同じ住所なのに表記揺れで「異なる住所」と判定され、て困っているという声が寄せられていました。 管理画面での従来の判定ロジックは単純で、半角スペースを除去して文字列比較をするだけでした。そのため、以下のようなケースで誤判定が発生していました。

  • 全角・半角の違い(1丁目 vs 1丁目
  • 漢数字・算用数字の違い(一丁目vs 1丁目
  • ハイフンの有無(1-2-3 vs1丁目2番3号

AmazonPayの無料導入による問題の顕在化

makeshopでは2024年9月からAmazonPayを無料導入したことで、AmazonPay利用ショップ様が大きく拡大しました。 AmazonPayでは、Amazonに登録された住所情報を利用するのですが、請求先住所と配送先住所が揺れているというケースが多くあったようで、何とかしてほしいという声が増えることになりました。

解決アプローチ

マネージャーからこのお題を振られた時、ちょうど数ヶ月前に見たリリース情報を思い出しました。それがgeolonia/normalize-japanese-addressesです。 blog.geolonia.com github.com このライブラリは日本の住所を正規化し、構造化されたデータとして返してくれる優れものです。住所の揺らぎを吸収しつつ、高精度な比較が可能になります。

実装

HonoでAPIサーバーとして実装 SmartCheckoutのバックエンドはGoで実装されています。GoからこのライブラリをHTTP API経由で呼び出せるようにするため、HonoAPIサーバーを追加しました。

住所比較ロジック

シンプルに2つの住所を正規化した結果を比較しています。正規化の結果は次のような構造になっています。

export type NormalizeResult = {
  /** 都道府県 */
  pref?: string
  /** 市区町村 */
  city?: string
  /**
   * 丁目・町字
   * 丁目の場合は、丁目名の後に漢数字で丁目が付与される。
   * 例:「青葉一丁目」
   */
  town?: string
  /** 住居表示または地番 */
  addr?: string
  /** 正規化後の住所文字列。完全に正規化された場合は、空の文字列が入ります。 */
  other: string
  /**
   * 住所の緯度経度
   * 注意: 正規化レベルが8でも、位置情報は8でもない場合もあります。
   */
  point?: NormalizeResultPoint
  /**
   * 住所文字列をどこまで判別できたかを表す正規化レベル
   * - 0 - 都道府県も判別できなかった。
   * - 1 - 都道府県まで判別できた。
   * - 2 - 市区町村まで判別できた。
   * - 3 - 丁目・町字まで判別できた。
   * - 8 - 住居表示住所または地番の判別ができた。
   */
  level: number
  /** 追加情報 */
  metadata: NormalizeResultMetadata
}

NormalizedResultの以下が一致していれば同じ住所であると判断しています。
otherについては若干加工してから比較しています。

  • level(正規化レベル)
  • pref(都道府県)
  • city(市区町村)
  • town(丁目・町字)
  • addr(住居表示または地番)
  • other(正規化できなかった部分)

おわりに

本来複雑なドメイン知識が必要な住所の比較という課題でしたが、geolonia/normalize-japanese-addressesを利用することであっさりと対応することができました。皆さんも住所で課題を抱えている時はぜひ使ってみてください。