我通过GeoFire在我的数据库中存储位置数据,这是结构:
geofire
-Ke1uhoT3gpHR_VsehIv
-Kdrel2Z_xWI280XNfGg
-g: "dr5regw90s"
-l
-0: 40.7127837
-1: -74.00594130000002
它可以将位置信息和地理位置数据存储在不同的节点中,但是我认为在这些地理阵列节点下存储 一些 额外数据是有利的,例如企业名称。通过这种方式,我只需拨打一次对Firebase的电话即可获取附近的地点及其名称。
这可以通过key_entered
方法实现吗?有人创建过类似的解决方案吗?即使位置信息一直在更新,这真的是一个想法吗?
感谢任何输入!
答案 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数据。