Firebase多路径更新会覆盖而不是更新子级

时间:2018-06-24 06:34:44

标签: android firebase firebase-realtime-database

我在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上体验过并设法解决了这个问题。

任何帮助将不胜感激。谢谢!

1 个答案:

答案 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)