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

时间:2016-07-13 00:43:52

标签: android firebase firebase-realtime-database geofire

我正在开发一个应用并在Firebase数据库中保存一些字符串,例如postedAtTimepostedBypostedOnDate。我想将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参考应该是什么,以便它与同一节点中的所有数据一起保存?

这里出了什么问题?请告诉我。

4 个答案:

答案 0 :(得分:36)

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

{
  "globalDependencies": {
    "react": "registry:dt/react#0.14.0+20160630100702",
    "react-dom": "registry:dt/react-dom#0.14.0+20160412154040",
    "react-redux": "registry:dt/react-redux#4.4.0+20160703120921",
    "redux": "registry:dt/redux#3.5.2+20160703092728",
    "redux-logger": "registry:dt/redux-logger#2.6.0+20160619033847"
  },
  "dependencies": {
    "redux-thunk": "registry:npm/redux-thunk#2.0.0+20160525185520"
  }
}

要获取数据,首先需要在{ "items" : { <itemId> : { "someData" : "someData", ... } }, "items_location" : { <itemId> : { <geofireData> ... } } } 节点上执行GeoQuery,然后获取items_location方法的数据。我的示例中的参数onKeyEnteredkey

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

编辑在一次API调用中保存项目数据和地理位置数据

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

答案 1 :(得分:12)

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

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

    您可以使用这些键从Geoquery结果获取常规项目。这就是为什么Geofire的事件被称为&#34; Key Entered&#34;,&#34; Key Exited&#34;等等。

    尝试将它们存储在一个节点中是一个坏主意,因为您将大多数静态数据(项目的属性)与高度易变的数据(地理位置信息)混合在一起。将两者分开可以提高性能,这就是Geofire强制执行的原因。

    虽然可能存在属性和地理数据同​​等动态/静态的用例,但GeoFire不支持将地理数据和其他属性保存在一个位置。

答案 2 :(得分:1)

您可以使用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);
       });
    }
}

答案 3 :(得分:1)

对于最近有相同问题的读者,可以使用Geofirestore库来实现,该库支持在Firebase Firestore数据库之上构建的应用程序的Geofire。