我在Android应用中使用Firebase实时数据库。出于数据标准化的目的,我将Player的数据保存到多个路径。 当我将其分别保存到每个路径时,一切正常。但是我尝试使用多路径更新保存数据,然后代替更新现有的子级,而是覆盖现有数据(如setValue中的数据)。我在某个地方读到了这种现象,但是我无法使其正常工作。
这是我的代码的相关代码段:
public void createPlayerInFirebaseDatabse(String playerId, FirebasePlayerEntity firebasePlayerEntity, final ICreateUser listener) {
Log.e(TAG, "DBHelper.createPlayerInFirebaseDatabase");
Map<String, Object> player = new HashMap<>();
player.put(playerId, firebasePlayerEntity);
Map<String, Object> isPlayerIn = new HashMap<>();
isPlayerIn.put(playerId, true);
Map<String, Object> playerUpdates = new HashMap<>();
playerUpdates.put("players/", player);
playerUpdates.put("leagues/" + firebasePlayerEntity.getLeagueCode() + "/playersIds/", isPlayerIn);
playerUpdates.put("teams/" + firebasePlayerEntity.getTeam() + "/playersIds", isPlayerIn);
databaseReference.updateChildren(playerUpdates)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.e(TAG, "DBHelper.createPlayerInFirebaseDatabase: onSuccess");
listener.onSuccess();
} else {
listener.onError(ErrorConsts.ERROR_CODE_DB_WRITING_FAILED);
}
}
});
仅当我将数据分别保存到每个路径时,它才会更新数据(不会覆盖),如下所示:
databaseReference.child(REF_PLAYERS).updateChildren(player);
databaseReference.child(REF_LEAGUES + "/" + firebasePlayerEntity.getLeagueCode() + "/" + REF_PLAYERS_IDS).updateChildren(isPlayerIn);
databaseReference.child(REF_TEAMS + "/" + firebasePlayerEntity.getTeam() + "/" + REF_PLAYERS_IDS).updateChildren(isPlayerIn)
我在javascript Firebase multi-location update overwriting instead of updating value上找到了此主题 但我想知道是否有人在Android上体验过并设法解决了这个问题。
任何帮助将不胜感激。谢谢!
答案 0 :(得分:2)
多位置更新会在您传入的Map
中的每个键上循环,并在该路径上执行setValue
。它不会进行“深度合并”,因此将替换地图中任何特定键处的所有内容。因此,您需要确保地图中的路径指向您要替换的确切数据。
现在,您的地图按键指向高一级。例如,您的地图说要用players
更新$playeruid/<playerEntity>
。这意味着您要用新播放器的数据替换players
下的所有内容,而这并不是您想要的。相反,您应该做的是告诉Firebase将players/$playeruid
更新为<playerEntity>
,从而使$playeruid
成为路径/密钥的一部分。
在代码中:
Map<String, Object> playerUpdates = new HashMap<>();
playerUpdates.put("players/" + playerId, firebasePlayerEntity);
playerUpdates.put("leagues/" + firebasePlayerEntity.getLeagueCode() + "/playersIds/" + playerId, true);
playerUpdates.put("teams/" + firebasePlayerEntity.getTeam() + "/playersIds/" + playerId, true);
databaseReference.updateChildren(playerUpdates)