正如我們在上一單元中所述,您應針對 DynamoDB 資料表所接收的請求數量進行最佳化。我們還提到 DynamoDB 沒有關聯式資料庫所具備的聯接。而是,您可以設計資料表,以允許您的請求中具有類似聯接的行為。
在此步驟中,我們在單一請求中擷取多種實體類型。在遊戲中,我們可能想擷取有關遊戲工作階段的詳細資訊。這些詳細資訊包括有關遊戲本身的資訊,例如開始時間、結束時間、放置者,以及有關遊戲玩家的詳細資訊。
該請求跨越兩種實體類型:Game 實體和 UserGameMapping 實體。但是,這並不意味著我們需要提出多個請求。
在您下載的程式碼中,fetch_game_and_players.py 指令碼位於 application/ 目錄中。該指令碼顯示了如何在單一請求中建構程式碼,以同時擷取遊戲的 Game 實體和 UserGameMapping 實體。
以下程式碼包含 fetch_game_and_players.py 指令碼。
import boto3
from entities import Game, UserGameMapping
dynamodb = boto3.client('dynamodb')
GAME_ID = "3d4285f0-e52b-401a-a59b-112b38c4a26b"
def fetch_game_and_users(game_id):
resp = dynamodb.query(
TableName='battle-royale',
KeyConditionExpression="PK = :pk AND SK BETWEEN :metadata AND :users",
ExpressionAttributeValues={
":pk": { "S": "GAME#{}".format(game_id) },
":metadata": { "S": "#METADATA#{}".format(game_id) },
":users": { "S": "USER$" },
},
ScanIndexForward=True
)
game = Game(resp['Items'][0])
game.users = [UserGameMapping(item) for item in resp['Items'][1:]]
return game
game = fetch_game_and_users(GAME_ID)
print(game)
for user in game.users:
print(user)
在該指令碼的開頭,我們匯入 Boto 3 庫和一些簡單的類,來表示應用程式程式碼中的物件。您可以在 application/entities.py 檔案中查看這些實體的定義。
指令碼的實際工作發生在單元中定義的 fetch_game_and_users 函數中。這類似於您在應用程式中定義的函數,用於此資料的所有端點。
fetch_game_and_users 函數可以進行一些操作。首先,它向 DynamoDB 發出查詢請求。此查詢使用 GAME#<GameId> 中的 PK。然後,請求排序金鑰在 #METADATA#<GameId> 和 USER$ 之間的任何實體。這將擷取 Game 實體 (其排序金鑰為 #METADATA#<GameId>),以及所有 UserGameMappings 實體,其金鑰以 USER# 開頭。字串類型的排序金鑰按 ASCII 字元程式碼排序。美元符號 ($) 在 ASCII 中的英鎊符號 (#) 之後,因此確保我們將在 UserGameMapping 實體中獲取所有映射。
收到回應後,我們將資料實體組合至應用程式已知的物件中。我們知道傳回的第一個實體是 Game 實體,因此我們從該實體建立 Game 物件。對於其餘實體,我們為每個實體建立一個 UserGameMapping 物件,然後將使用者陣列附加至 Game 物件。
指令碼的末尾顯示該函數的用法,並列印出結果物件。您可以在終端機中使用以下命令執行此指令碼。
該指令碼應將 Game 物件和所有 UserGameMapping 物件列印至主控台。
Game<3d4285f0-e52b-401a-a59b-112b38c4a26b -- Green Grasslands>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- branchmichael>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- deanmcclure>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- emccoy>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- emma83>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- iherrera>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- jeremyjohnson>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- lisabaker>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- maryharris>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- mayrebecca>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- meghanhernandez>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- nruiz>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- pboyd>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- richardbowman>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- roberthill>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- robertwood>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- victoriapatrick>
UserGameMapping<3d4285f0-e52b-401a-a59b-112b38c4a26b -- waltervargas>
此指令碼顯示如何在單一 DynamoDB 請求中對資料表建模,並編寫查詢以擷取多種實體類型。在關聯式資料庫中,您可以在單一請求中使用聯接,以從不同資料表中擷取多種實體類型。使用 DynamoDB,您可以專門為資料建模,以便將應當一起存取的實體在單一資料表中彼此相鄰。這種方法取代了在典型的關聯式資料庫中進行聯接的需求,並在您擴展應用程式時保持了高效能。