使用Python操作Amazon DynamoDB:电影数据管理实战教程
Amazon DynamoDB是一种完全托管的NoSQL数据库服务,提供快速且可预测的性能,能够实现无缝扩展。本文将通过一个电影数据管理的实战案例,演示如何使用Python SDK(Boto3)与DynamoDB进行交互。
1. 准备工作
首先需要安装必要的Python包:
import boto3
from boto3.dynamodb.conditions import Key
from decimal import Decimal
import json
2. 创建DynamoDB表
2.1 表结构设计
电影数据表的设计需要考虑以下因素:
- 分区键(Partition Key):使用电影发行年份(year)
- 排序键(Sort Key):使用电影标题(title)
这种设计允许我们:
- 快速查询特定年份的电影
- 精确获取某年某部电影的信息
def create_table(self, table_name):
try:
self.table = self.dyn_resource.create_table(
TableName=table_name,
KeySchema=[
{"AttributeName": "year", "KeyType": "HASH"}, # 分区键
{"AttributeName": "title", "KeyType": "RANGE"}, # 排序键
],
AttributeDefinitions=[
{"AttributeName": "year", "AttributeType": "N"},
{"AttributeName": "title", "AttributeType": "S"},
],
BillingMode='PAY_PER_REQUEST',
)
self.table.wait_until_exists()
except ClientError as err:
logger.error("创建表失败: %s", err)
raise
3. 数据操作
3.1 批量写入数据
使用批量写入操作可以高效地加载大量数据:
def write_batch(self, movies):
try:
with self.table.batch_writer() as writer:
for movie in movies:
writer.put_item(Item=movie)
except ClientError as err:
logger.error("批量写入失败: %s", err)
raise
3.2 添加单条记录
添加单部电影信息:
def add_movie(self, title, year, plot, rating):
try:
self.table.put_item(
Item={
"year": year,
"title": title,
"info": {"plot": plot, "rating": Decimal(str(rating))},
}
)
except ClientError as err:
logger.error("添加电影失败: %s", err)
raise
4. 查询与扫描
4.1 精确查询
查询特定年份的电影:
def query_movies(self, year):
try:
response = self.table.query(KeyConditionExpression=Key("year").eq(year))
except ClientError as err:
logger.error("查询失败: %s", err)
raise
else:
return response["Items"]
4.2 范围扫描
扫描特定年份范围内的电影:
def scan_movies(self, year_range):
movies = []
scan_kwargs = {
"FilterExpression": Key("year").between(year_range["first"], year_range["second"]),
"ProjectionExpression": "#yr, title, info.rating",
"ExpressionAttributeNames": {"#yr": "year"},
}
try:
done = False
start_key = None
while not done:
if start_key:
scan_kwargs["ExclusiveStartKey"] = start_key
response = self.table.scan(**scan_kwargs)
movies.extend(response.get("Items", []))
start_key = response.get("LastEvaluatedKey", None)
done = start_key is None
except ClientError as err:
logger.error("扫描失败: %s", err)
raise
return movies
5. 更新与删除
5.1 条件更新
更新电影评分和剧情简介:
def update_movie(self, title, year, rating, plot):
try:
response = self.table.update_item(
Key={"year": year, "title": title},
UpdateExpression="set info.rating=:r, info.plot=:p",
ExpressionAttributeValues={":r": Decimal(str(rating)), ":p": plot},
ReturnValues="UPDATED_NEW",
)
except ClientError as err:
logger.error("更新失败: %s", err)
raise
else:
return response["Attributes"]
5.2 删除记录
删除特定电影:
def delete_movie(self, title, year):
try:
self.table.delete_item(Key={"year": year, "title": title})
except ClientError as err:
logger.error("删除失败: %s", err)
raise
6. 实战场景
6.1 交互式操作
通过命令行交互方式管理电影数据:
def run_scenario(table_name, movie_file_name, dyn_resource):
movies = Movies(dyn_resource)
if not movies.exists(table_name):
movies.create_table(table_name)
# 添加用户自定义电影
my_movie = {
"title": input("电影标题: "),
"year": int(input("发行年份: ")),
"rating": float(input("评分(1-10): ")),
"plot": input("剧情简介: ")
}
movies.add_movie(**my_movie)
# 查询示例
if input("查询《指环王》信息?(y/n) ").lower() == 'y':
movie = movies.get_movie("The Lord of the Rings: The Fellowship of the Ring", 2001)
pprint(movie)
7. 最佳实践
- 合理设计主键:根据查询模式选择分区键和排序键
- 使用批量操作:减少API调用次数
- 适当使用投影:只检索需要的属性
- 处理大结果集:使用LastEvaluatedKey分页
- 错误处理:捕获并妥善处理ClientError
8. 总结
通过这个电影数据管理案例,我们学习了DynamoDB的基本操作,包括:
- 表的创建与管理
- 数据的增删改查
- 查询与扫描操作
- 条件更新与批量操作
这些技术可以应用于各种需要高性能、可扩展数据存储的场景,如用户配置存储、游戏状态管理、物联网数据处理等。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考