Cloud Firestore便利ですよね。
Cloud Firestoreで「半径〇km以内にあるスポットを検索する」みたいな実装をしたかったのでGeoFireXを使って実装してみました。
https://github.com/codediodeio/geofirex
Cloud Firestoreでの緯度経度の情報の取扱について
Cloud FirestoreにはGeoPoint型あって、緯度経度の情報はGeoPoint型として保存する必要があります。
1
2
3
4
5
6
|
import firebase from 'firebase'
const spot = {
name: 'spot1',
location: new firebase.firestore.GeoPoint(latitude, longitude)
}
|
geohashの設定について
GeoFireXを利用する場合は位置情報のデータだけじゃだめでGeohashも用意する必要があります。
https://ja.wikipedia.org/wiki/%E3%82%B8%E3%82%AA%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5
僕の場合はngeohashを使ってhashを生成しました。
1
2
3
4
5
6
7
8
|
const geohash = require('ngeohash');
const spot = {
"name": "Spot A",
"location": {
geohash: geohash.encode(latitude, longitude)
geopoint: new firebase.firestore.GeoPoint(latitude, longitude)
}
|
このようにGeoPoint,Geohashの両方を用意しないとGeoFireXを使って検索しても結果が取得出来ません。
GeoFireXを利用して検索を行う
半径〇キロ以内の検索にはGeoFireXを利用しました。
以下のサンプルコードを見てもらえればわかりますが、簡単に「半径〇km以内にあるスポットを検索する」みたいな実装ができます。
例: 半径100km以内のスポットを検索する。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// Init Firebase
import firebase from 'firebase';
const firestore = firebase.firestore({
timestampsInSnapshots: true
})
// Init GeoFireX
import * as geofirex from 'geofirex';
const geo = geofirex.init(firestore);
const spot = geo.collection('spot')
const now = {
lat: 40.1
lng: -119.1
}
const center = geo.point(now.lat, now.lng);
const radius = 100; // 100km
const field = 'location';
const query = spot.within(center, radius, field);
query.subscribe((spots) => {
console.log(spots)
})
|
検索時に取得条件、ソート、取得数などを設定する
collectionを取得する段階でwhere,orderBy,limitなどの指定ができます。
1
|
const spot = geo.collection('spot', ref => ref.where("star", ">", 3).limit(4))
|
最後に
GeoFireXを使えばFirestoreでの緯度経度の検索は簡単に実装できるのでますね。
そこまでハマることも無いのでおすすめです。
ちなみに同じようなライブラリでgeofirestore-jsもありますが、GeoFireXのほうが簡単に実装できる印象があります。
ただ、リアルタイムに位置情報が変わっていくのを反映したい場合にはgeofirestore-jsのほうが良さそうです。