在GeoFire节点下存储额外数据

时间:2017-03-05 12:20:18

标签: firebase geofire

我通过GeoFire在我的数据库中存储位置数据,这是结构:

geofire
  -Ke1uhoT3gpHR_VsehIv
  -Kdrel2Z_xWI280XNfGg
    -g: "dr5regw90s"
    -l
      -0: 40.7127837
      -1: -74.00594130000002

它可以将位置信息和地理位置数据存储在不同的节点中,但是我认为在这些地理阵列节点下存储 一些 额外数据是有利的,例如企业名称。通过这种方式,我只需拨打一次对Firebase的电话即可获取附近的地点及其名称。

这可以通过key_entered方法实现吗?有人创建过类似的解决方案吗?即使位置信息一直在更新,这真的是一个想法吗?

感谢任何输入!

2 个答案:

答案 0 :(得分:11)

首先,您为应用程序使用的结构是错误的。

让我们举一个用户应用

的例子

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

a list of user details for each user
a list of latitude and longitude coordinates for each user

您正尝试将两者存储在相同的结构中

"users" : {
    <userId> : {
        "userData" : "userData",
         <geofireData> 
        ...
    }
}

尝试将userdata和geofiredata存储在一个节点中是一个坏主意,因为您将大多数静态数据(用户的属性)与高度易变的数据(地理位置信息)混合在一起。将两者分开导致更好的性能,这就是Geofire强制执行的原因。

这就是为什么当您尝试将地理位置数据添加到用户节点时,它会覆盖该节点的先前用户详细信息。

您的数据库结构应该是这样的。

"Users" : {
    <UserId> : {
        "UserData" : "UserData",
        ...
    }
}
"Users_location" : {
    <UserId> : {
        <geofireData> ...
    }
}

因此,对于相同的用户ID,您可以创建2个结构,一个用于用户详细信息,另一个用于该用户的地理位置详细信息。

如何推送用户并设置地理位置数据。

String userId = ref.child("users").push().getKey();

ref.child("users").child(userId).setValue(user);

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

您在地理定位中使用的userId与push()期间获得的userId相同。

因此,对于每个userId,您在anotehr结构中的一个结构和位置详细信息中都有用户详细信息。

要获取数据,首先需要在users_location节点上执行GeoQuery,然后获取onKeyEntered方法的数据。参数键是我的例子中的userId。

geoFire=newGeoFire(FirebaseDatabase.getInstance().getReference().child("users_location");
geoQuery = geoFire.queryAtLocation(geoLocation), radius);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
         //retrieve data
//use this key which is userId to fetch user details from user details structure
    }
};    

快乐编码:)

答案 1 :(得分:1)

可能已经晚了,但以防万一其他人也面临同样的问题。

很有可能将GeoFire数据与现有数据集成和处理。 许多开发人员面临的主要挑战是,如本期geofire-java/issues/134所述,他们不能不使用cout删除现有数据就无法更新GeoFire地理位置。

这是我的解决方案。

1。在FireBase上使用GeoFire设置混合数据

让我们考虑以下结构:

geoFire.setLocation("id", location);

您可以使用|-userExtra : |-userId1 : |- userId : "userId1", |- userName : "Name1", |- <geofireData> (i and g) |... |-userId2 : |- userId : "userId2", |- userName : "Name2", |- <geofireData> (i and g) |... 生成geoHash并将值直接设置为Firebase中的子级。

GeoHash geoHash = new GeoHash(location)

2。使用GeoFire获取混合数据

关于此问题: 这可以通过key_entered方法实现吗?有没有人创造过类似的解决方案?即使位置信息不断更新,这真的不是一个好主意吗?

我想说,您不能仅使用/*Java Code*/ void setGeoFireMixData(UserExtra user, Location location){ DatabaseReference ref = FirebaseDatabase.getInstance().getReference(); ref = ref.child("users").child(user.userId); //Setting userData if needed ref.child("userId").setValue(user.id); ref.child("Name").setValue(user.name); // .... other references //Setting GeoFire Data GeoHash geoHash = new GeoHash(location); ref.child("l").setValue(Arrays.asList(location.latitude, location.longitude)); ref.child("g").setValue(geoHash.getGeoHashString()); } GeoQueryEventListener来检索额外的数据和GeoFire。您将需要使用onKeyEntered。为此,您可以考虑以上定义的结构来定义数据的PoJo。

GeoQueryDataEventListener

UserExtra类可以定义如下:

...
GeoQueryDataEventListener geoQueryDataEventListener = new GeoQueryDataEventListener() {
  @Override
  public void onDataEntered(DataSnapshot dataSnapshot, GeoLocation location) {
      UserExtra user = dataSnapshot.getValue(UserExtra.class);
      actionOnUser(user);
  }
  ...
};
...
geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude,longitude), 0.5);
geoQuery.addGeoQueryDataEventListener(geoQueryDataEventListener);
...

这将为您提供节点中的所有数据,包括geoFire数据。