如何在Firebase数据库中保存GeoFire坐标以及其他项目?

我正在开发一个应用程序,并在FirebaseDatabase保存一些Strings如postedAtTime,postedBy,postedOnDate。 我想将GeoFire坐标保存在上面所有string保存的同一个节点中,以便稍后我可以轻松地进行查询。

下面是我保存所有string的path: 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); } 

以下是它在数据库中的保存方式:

在这里输入图像描述

我想要的是,我想将GeoFire坐标保存在同一个节点中,这里是-KLIoLUsI0SpQZGpV1h4 。 这只是一个推送ID,随机生成。

我尝试了这个参考: geoFire = new GeoFire(firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/")); 然后如上所示用其他物品推动它。 但是,这只保存GeoFire坐标,而不是节点下的其他项: requests

那么,我的GeoFire参考应该如何保存,以及同一节点中的所有数据?

这里怎么了? 请告诉我。

弗兰克的回答是正确的,但我想举个例子。 你的数据库结构应该是这样的。

 "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 } }; 

希望这可以帮助。

编辑如何推送项目并设置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)); 

编辑将项目数据和geofire数据保存在一个API调用中

 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); 

当您使用Geofire时,您有两个数据列表:

  1. 具有常规属性的项目列表
  2. 您通过Geofire查询的地理杂志索引列表及其关联的键

您可以使用键从Geoquery结果获取常规项目。 这就是为什么Geofire的事件被称为“钥匙input”,“退出钥匙”等

尝试将它们存储在一个节点中是一个糟糕的主意,因为您主要将静态数据(项目的属性)与高度不稳定的数据(地理位置信息)混合在一起。 分离出来的两个导致更好的性能,这就是为什么Geofire强制执行它。

尽pipe可能存在使用情况下的属性和地理数据是同等dynamic/静态的,但GeoFire不支持将地理数据和其他属性保存在一个位置。

您可以使用Firebasefunction在每个新条目中为您input

 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); }); } }