web-dev-qa-db-ja.com

Firebaseデータベースの他のアイテムとともにGeoFire座標を保存する方法は?

アプリを開発し、postedAtTimepostedBypostedOnDateなどの文字列をFirebaseデータベースに保存しています。上記のすべての文字列が保存されている同じノードにGeoFire座標を保存して、後で簡単にクエリを実行できるようにします。

すべての文字列を保存するパスは次のとおりです。

databaseReferenceHRequests = firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/");

これは私がそれを保存する方法です:

// in onButtonClicked method:
postNewRequest(null, imageUID, MainActivity.userName.getText().toString(), time, date, utcFormatDateTime, MainActivity.userEmail.getText().toString(), geoFire);

// the method:
public void postNewRequest(Bitmap bitmap, String imageUIDh, String postedBy, String postedAtTime, String postedOnDate, String utcFormatDateTime, String userEmail, GeoFire geoFire) {
    HRequest hRequest = new HelpRequest(null, imageUIDh, postedBy, postedAtTime, postedOnDate, utcFormatDateTime, userEmail, geoFire);
    databaseReferenceHRequests.Push().setValue(hRequest);
}

データベースに保存する方法は次のとおりです。

database structure screenshot

必要なのは、同じノードにGeoFire座標を保存することです。これは-KLIoLUsI0SpQZGpV1h4 ここに。これは単なるプッシュIDであり、ランダムに生成されます。

私はこの参照を与えて試しました:

geoFire = new GeoFire(firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/"));

次に、上記のように他のアイテムでプッシュします。ただし、これはGeoFire座標のみを保存し、ノードrequestsの下の他のアイテムは保存しません。

それで、同じノード内のすべてのデータとともに保存されるように、GeoFire参照はどうあるべきでしょうか?

ここで何が問題になっていますか?私にお知らせください。

17
Hammad Nasir

フランクの答えは正しいですが、例を挙げたいと思います。データベース構造は次のようになります。

{
"items" : {
    <itemId> : {
        "someData" : "someData",
        ...
    }
  },
"items_location" : {
    <itemId> : {
        <geofireData> ...
    }
  }
}

データを取得するには、最初にitems_locationノードでGeoQueryを実行してから、onKeyEnteredメソッドでデータを取得する必要があります。パラメーターkeyは、私の例ではitemIdです。

geoFire = new GeoFire(FirebaseDatabase.getInstance().getReference().child("items_location");
geoQuery = geoFire.queryAtLocation(geoLocation), radius);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
         //retrieve data
    }
};    

お役に立てれば。

[〜#〜] edit [〜#〜]アイテムをプッシュして、geofireデータを設定する方法。

String itemId = ref.child("items").Push().getKey();

ref.child("items").child(itemId).setValue(item);

geoFire = new GeoFire(ref.child("items_location"));
geoFire.setLocation(itemId, new GeoLocation(lattitude, longitude));

[〜#〜] edit [〜#〜] 1回のAPI呼び出しでアイテムデータとgeofireデータを保存する

GeoHash geoHash = new GeoHash(new GeoLocation(latitude, longitude));
Map<String, Object> updates = new HashMap<>();
updates.put("items/" + itemId, item);
updates.put("items_location/" + itemId + "/g", geoHash.getGeoHashString());
updates.put("items_location/" + itemId + "/l", Arrays.asList(latitude, longitude));
ref.updateChildren(updates);
38
Wilik

Geofireを使用する場合、2つのデータリストがあります。

  1. 通常のプロパティを持つアイテムのリスト
  2. geohashインデックスとそれに関連付けられたキーのリスト。Geofireでクエリします

キーを使用して、Geoqueryの結果から通常のアイテムを取得します。そのため、Geofireのイベントは「キー入力」、「キー終了」などと呼ばれます。

それらを1つのノードに保存しようとするのは悪い考えです。なぜなら、ほとんど静的なデータ(アイテムのプロパティ)と非常に揮発性の高いデータ(ジオロケーション情報)を混合しているからです。 2つを分離するとパフォーマンスが向上するため、Geofireはそれを実施します。

プロパティと地理データが同等に動的/静的であるユースケースが存在する場合がありますが、GeoFireは地理データと他のプロパティを単一の場所に保持することをサポートしていません。

13

同じ質問でこの投稿に最近アクセスした人たちにとって、これは Geofirestore ライブラリで可能です。これは、Firebase Firestoreデータベースの上に構築されたアプリのGeofireをサポートします。

1
DHShah01

新しいエントリごとにFirebase関数を使用して入力できます

let functions = require('firebase-functions');

let GeoFire = require('geofire');

exports.testLocation = functions.database.ref('/items/{item}').onWrite(event => {
let data = event.data.val();
   console.log(data);
   console.log(event.params.item);

   if (data.location && data.location.coords) {

       console.log('Update GeoFire');

       let ref = event.data.adminRef.parent.parent.child('/items_locations'));

       let key = event.params.test;
       let location = [data.location.coords.latitude, data.location.coords.longitude]);
       let geoFire = new GeoFire(ref);

       geoFire.set(key, location).then(() => {
          console.log('Update succesfull');
       }).catch(error => {
          console.log(error);
       });
    }
}
1
Jonas Tomanga