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

Ham*_*sir 17 android firebase geofire firebase-realtime-database

我开发一个应用程序,并节省一些字符串一样postedAtTime,postedBy,postedOnDate在火力地堡数据库.我想将GeoFire坐标保存在保存所有上述字符串的同一节点中,以便稍后我可以轻松地进行查询.

这是我保存所有字符串的路径:

databaseReferenceHRequests = firebaseDatabase.getReferenceFromUrl("https://appName-e1a35.firebaseio.com/requests/");
Run Code Online (Sandbox Code Playgroud)

这是我如何保存它:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

以下是它如何保存在数据库中:

数据库结构截图

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

我试过这个参考:

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

然后用上面显示的其他项目推送它.但是,这只保存了GeoFire坐标而不保存节点下的其他项目requests.

那么,我的GeoFire参考应该是什么,以便它与同一节点中的所有数据一起保存?

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

Wil*_*lik 38

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

{
"items" : {
    <itemId> : {
        "someData" : "someData",
        ...
    }
  },
"items_location" : {
    <itemId> : {
        <geofireData> ...
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

要获取数据,首先需要在items_location节点上执行GeoQuery,然后获取onKeyEntered方法的数据.该参数keyitemId从我的例子.

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
    }
};    
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

编辑 如何推送项目并设置地理空间数据.

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));
Run Code Online (Sandbox Code Playgroud)

编辑在一次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);
Run Code Online (Sandbox Code Playgroud)


Fra*_*len 13

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

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

您可以使用键从Geoquery结果获取常规项.这就是为什么Geofire的事件被称为"Key Entered","Key Exited"等.

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

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