如何构建我的运动管理器Firebase数据库

时间:2017-07-09 20:56:48

标签: android firebase firebase-realtime-database nosql

我正在建立一个体育经理应用程序,让用户创建自己的比赛并更新比赛结果,以便为其他参与者提供咨询。

我读了很多关于数据库是多么平坦(我来自SQL :-)并看过Firebase团队的许多视频教程。

此时我有这样的结构:

{sport-manager :
    ...
    groups : {
        "groupId1" : {
            competitionId : "competitionId1"
            name : "Group A",
            type : "LEAGUE"
        },
        "groupId2" : {
            competitionId : "competitionId1"
            name : "West playoofs",
            type : "PLAYOFFS"
        },
        ...
    },
    players : {
        "playerId1" : {
            birthday : 351408600000,
            firsName : "Jhon",
            lastName : "Doe",
            shirtNumber : 0,
            teamId : "teamId1"
        },
        ...
    },
    teams : {
        "teamId1" : {
            competitionId : "competitionId1"
            name : "Team 1",
            },
        ...
    },
    teamGroupStats : {
        "groupId1" : {
            "teamId1" : {
                goalsAgainst: 0,
                goalsFavor: 0,
                matchesDraw: 0,
                matchesLoss: 0,
                matchesPlayed: 0,
                matchesWin: 0,
                points: 0,
                teamName: "Team 1",
            },
            "teamId2" : {
            ...
            },
            ...
        },
        "groupId2" : {
            "teamId2" : {
            ...
            },
            ...
        }
        ...
    }
}

通过这种结构,我可以通过这种方式查询ListView适配器,其中包含属于组的所有团队的数据:

DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
Query groupQuery = mDatabase.child("teamGroupStats").child("groupId1")

或者当我必须从确定的团队中获得玩家时:

Query playersQuery = mDatabase.child("players").orderByChild("teamId").equalTo("teamId1");

到目前为止,这么好。当我不得不从这个结构中删除团队时,我的问题就来了。为避免完整性问题,我使用multipath update删除所有。

  • 一支球队可以拥有一名或多名球员
  • 团队可以是一个或多个团队的一部分。

考虑到这一点,我可以删除所有球员的任何球队。

Map<String, Object> deleteMap = new HashMap<>();
deleteMap.put("teams/teamId1", null);

Query playersQuery = mDatabase.child("players").orderByChild("teamId").equalTo("teamId1");
playersQuery.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot playerSnapshot : dataSnapshot.getChildren()){
            deleteMap.put("players/" + playerSnapshot.getKey(), null);
        }

        // Delete all in one call!
        mDatabase.updateChildren(deleteMap);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

如何使用&#34; teamId1&#34;进行查询以获取所有路径结构中有一个关键的关键&#34; teamGroupStats&#34;? 他的这个结构对我需要的用途有好处吗?

2 个答案:

答案 0 :(得分:0)

恕我直言,你的数据库结构非常好。关于你的问题,你不能像你说的那样得到所有的路径。你能做什么,就是以与添加数据相同的方式删除数据。因此,为了删除所有数据,我使用这种方法重新命令:

private static void deleteTeam(String teamId) {
    Map<String, Object> map = new HashMap<>();
    map.put("/teams/" + teamId, null);
    map.put("/teamGroupStats/groupId1/" + teamId, null);
    map.put("/players/playerId1/teamId/", null);
    databaseReference.updateChildren(map);
}

更通用的方法是:

private static void deleteTeam(String reference, String teamId) {
    Map<String, Object> map = new HashMap<>();
    map.put(reference, null);
    databaseReference.updateChildren(map);
}

如果您需要查询数据库以获取其他数据,请使用getRef()方法获取引用并将这些值传递给第二种方法。

您的所有数据都会以原子方式立即删除。

希望它有所帮助。

答案 1 :(得分:0)

最后我找到了一个解决方案。我修改了我的数据库以存储团队属于团队结构的所有组ID。

teams : {
    "teamId1" : {
        competitionId : "competitionId1"
        groups : {
            "groupId1" : true,
            "groupId6" : true,
            ...
        },
        name : "Team 1",
        },
    ...

有了这些信息,我可以在playersQuery的监听器中添加一个内部ValueEventListener并进行更新/删除。

public static void deleteTeam(final String teamId){
    Map<String, Object> deleteMap = new HashMap<>();
    deleteMap.put("teams/" + teamId, null);

    DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
    Query playersQuery = mDatabase.child("players").orderByChild("teamId").equalTo(teamId);
    playersQuery.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot playerSnapshot : dataSnapshot.getChildren()){
                String playerId = playerSnapshot.getKey();
                deleteMap.put("players/" + playerId, null);
            }

            mDatabase.child("teams").child(teamId).child("groups")
                .addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for (DataSnapshot groupSnapshot : dataSnapshot.getChildren()){
                        String groupId = groupSnapshot.getKey();
                        deleteMap.put("teamGroupStats/" + groupId + "/" + teamId, null);
                    }

                    // Delete all in one call!
                    mDatabase.updateChildren(deleteMap);
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    System.out.println("The read failed: " + databaseError.getCode());
                }
            });
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            System.out.println("The read failed: " + databaseError.getCode());
        }
    });
}

我对内部监听器并不十分肯定,我不得不对我的数据库结构进行一些改动,但这样做很好。

如果有人知道更好的方法,我可以阅读它。谢谢!