2017-07-09 26 views
1

我正在構建一個體育經理應用程序,讓用戶創建自己的比賽並更新比賽結果,以便爲其他參與者提供諮詢服務。如何組織我的體育經理Firebase數據庫

我讀了很多關於數據庫的平坦度(我來自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") 

或者當我得從determinated隊球員:

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

到目前爲止,不錯。當我必須從這個結構中刪除一個團隊時,我的問題就來了。爲避免完整性問題,我使用多路徑更新來刪除所有內容。

  • 團隊可以有一個或多個玩家
  • 團隊可以是一個或多個組的一部分。

考慮到這一點,我可以刪除他的所有球員任何球隊。

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) { 

    } 
}); 

我怎樣才能使一個查詢來獲取所有以「teamId1」具有在結構「teamGroupStats」 secundary關鍵路徑? 他的這種結構適合我需要的用途嗎?

回答

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()); 
     } 
    }); 
} 

我也不是很肯定的內聽者,我不得不做出一個變化不大我的數據庫結構,但是這個工作正常。

如果有人知道更好的方法來做到這一點,我很樂意閱讀。謝謝!

0

恕我直言,你的數據庫結構非常好。關於你的問題,你不能像你說的那樣得到所有的路徑。你可以做什麼,就像刪除數據一樣刪除數據。因此,爲了刪除所有數據我recomand您使用此方法:

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()方法得到參考,並通過這些值的第二方法。

的所有數據將在一次原子被刪除。

希望它有幫助。

+0

問題在於,我並不是每個團隊或團隊中只有一名球員只有一個團隊。我不能使用你的方法,因爲我不知道每個團隊或團隊所屬團隊的名單,直到我對數據庫進行查詢(並且異步調用無助於這樣做) –

+0

In在這種情況下,進行查詢,查找所需的所有數據並將該數據傳遞給方法。我用更通用的方法更新了我的答案。 –

+0

我感謝您的幫助,但是這種通用方法不起作用。您只在映射中填充一對「path,null」,並且不會進行多路徑刪除。刪除一個團隊和他在我的帖子中顯示的所有球員的工作方式很好,我的問題是從「teamGroupStats」中獲得二級密鑰(團隊ID)。如果無法完成,也許我的結構有問題。 –