【JS/TS】geofirestoreを使って位置情報を検索条件で使用する
はじめに
現在ReactNative
で開発中のアプリのバックエンドとしてFirebase
を使用しています。
今さら説明の必要はないかと思いますがFirebase
は、プッシュ通知や認証などを一手に引き受けてくれる優れもので、firestore
というNoSQL
のDB
もあります。
無料枠でも使いこなせば高クオリティのものが出来上がるため重宝しているのですが、今回firestore
に格納したデータの「位置情報」に対して検索条件を付けたくなり、少し手間だったので記事にします。
※イメージとして、 「現在地から半径Nキロ以内」のデータを取得してきてマップにプロット するようなアプリを想定しています。
GeoPoint
firestore
にはGeoPoint
という形式で位置情報が保存されます。
- 参考:GeoPoint
値の保持はこれで問題ないのですが、この値を基にクエリを作成しようとした時に問題が発生します。
「緯度と経度を用いた複合条件ができない」 ためです。
そのあたりで困っている方はやはり多いようで、有志の方が作成した拡張ライブラリがありました。
geofirestore
というものです。
インストール
yarn geofirestore
使い方
基本形
firebase
のチュートリアルに沿って実装している場合は組み込みは容易です。
まず、通常のfirestore
インスタンスから新たにGeoFirestore
インスタンスを作成します。
import firebase from 'firebase/app';
import * as Geofirestore from 'geofirestore';
// まずはfirebaseインスタンスを初期化
const firebaseApp: firebase.app.App = firebase.initializeApp({
apiKey: "xxxxxxx",
/* ...略... */
});
// firestoreインスタンスを作成
const db: firebase.firestore.Firestore = firebaseApp.firestore();
// firestoreインスタンスからGeoFirestoreインスタンスを作成
const gdb: Geofirestore.GeoFirestore = Geofirestore.initializeApp(db);
データ作成時
GeoFirestore
インスタンスはfirestore
インスタンスとほぼ同じ使い勝手で利用することができます。
位置情報を持たせてクエリを投げるためcoordinates
というフィールド名でGeoPoint
型の値を格納します。
gdb.collection('test').add({
data1: 'hogehoge',
data2: 'fugafuga',
// coordinatesというフィールド名でGeoPointを設定(引数にはlat,lon)
coordinates: new firebase.firestore.GeoPoint(35.306767, 138.9606928),
})
成功するとcoordinates
以外にもg
というフィールドが作成されていました。
geohash
等の細かい値を持っているので、後述のクエリはこちらの値を参照しているのかもしれません。
クエリ実行時
GeoPoint
に関わらない値を扱う場合のクエリ(where()
等)はfirestore
と使い勝手が同じです。
GeoFirestore
においてGeoPoint
に関するクエリを扱う場合はnear()
を使います。
gdb.collection('test').near({
// 中心となる座標をGeoPointで指定
center: new firebase.firestore.GeoPoint(35.306767, 138.9606928),
// 中心座標からの半径(km)を指定
radius: 5
}).get().then((d) => {
// ...略
});
まとめ
今回はgeofirestore
を利用したFirestore
中のGeoPoint
を使った検索クエリの発行方法について紹介しました。
素のFirestore
だけでなくreact-native-firestore
でも同様に動作したので、Web
やモバイルを問わずに利用できます。
使い勝手もfirestore
の書き方をそのまま流用できるので、位置情報絡みのアプリケーションを開発する場合はオススメです。
Discussion