Peewee ORM 查询操作详解:从基础CRUD到高级批量处理

Peewee ORM 查询操作详解:从基础CRUD到高级批量处理

概述

Peewee 是一个轻量级 Python ORM(对象关系映射)工具,提供了简洁而强大的数据库操作接口。本文将深入讲解 Peewee 中的查询操作,涵盖从基础的 CRUD(创建、读取、更新、删除)到高级的批量处理技巧。

创建记录

基本创建方法

Peewee 提供了多种创建记录的方式:

# 方法1:使用create()直接创建
user = User.create(username='Charlie')

# 方法2:先实例化再保存
user = User(username='Charlie')
user.save()  # 返回受影响的行数

# 方法3:使用insert()不创建模型实例
user_id = User.insert(username='Charlie').execute()

外键关联创建

处理外键关系时,可以直接传递模型实例:

tweet = Tweet.create(user=user, message='Hello!')
# 等价于
tweet = Tweet.create(user=user.id, message='Hello!')

批量插入

对于大量数据插入,Peewee 提供了多种优化方案。

基础批量插入

data = [{'username': 'user1'}, {'username': 'user2'}]

# 方法1:循环+事务
with db.atomic():
    for item in data:
        User.create(**item)

高效批量插入

使用 insert_many() 可以显著提高性能:

# 使用字典列表
User.insert_many(data).execute()

# 使用元组列表(需指定字段)
users = [('user1',), ('user2',)]
User.insert_many(users, fields=[User.username]).execute()

分批次插入

对于超大数据集,建议分批次处理:

from peewee import chunked

with db.atomic():
    for batch in chunked(data, 100):  # 每批100条
        User.insert_many(batch).execute()

替代方案

bulk_create() 方法可以直接插入未保存的模型实例:

users = [User(username='user%s' % i) for i in range(1000)]
with db.atomic():
    User.bulk_create(users, batch_size=100)

更新记录

单个记录更新

保存已有主键的记录会自动转为更新操作:

user = User.get(User.username == 'Charlie')
user.username = 'Charles'
user.save()  # 执行UPDATE操作

批量更新

# 更新所有创建于今天的推文
today = datetime.today()
query = Tweet.update(is_published=True).where(Tweet.creation_date < today)
updated_count = query.execute()

原子更新

避免竞态条件的原子更新:

# 不安全方式(有竞态条件风险)
stat = Stat.get(Stat.url == request.url)
stat.counter += 1
stat.save()

# 安全方式(原子操作)
query = Stat.update(counter=Stat.counter + 1).where(Stat.url == request.url)
query.execute()

高级更新示例

# 给所有员工加10%薪水的奖金
Employee.update(bonus=(Employee.bonus + (Employee.salary * .1))).execute()

# 使用子查询更新用户推文数
subquery = Tweet.select(fn.COUNT(Tweet.id)).where(Tweet.user == User.id)
User.update(num_tweets=subquery).execute()

更新或插入(Upsert)

替换式Upsert

# 如果用户存在则替换,不存在则插入
User.replace(username='the-user', last_login=datetime.now()).execute()
# 等价于
User.insert(username='the-user', last_login=datetime.now()).on_conflict_replace().execute()

MySQL风格Upsert

User.insert(username='huey', login_count=1).on_conflict(
    preserve=[User.last_login],  # 保留插入值
    update={User.login_count: User.login_count + 1}  # 递增计数
).execute()

PostgreSQL/SQLite风格Upsert

User.insert(username='huey', last_login=now, login_count=1).on_conflict(
    conflict_target=[User.username],  # 冲突目标
    preserve=[User.last_login],
    update={User.login_count: User.login_count + 1}
).execute()

高级Upsert示例

# 仅当新值大于原值时更新
query = (KV.insert(key='k1', value=10)
         .on_conflict(
             conflict_target=[KV.key],
             update={KV.value: KV.value + EXCLUDED.value},
             where=(EXCLUDED.value > KV.value)))
query.execute()

总结

Peewee 提供了丰富而灵活的数据库操作接口,从简单的单记录操作到复杂的批量处理都能高效完成。关键点包括:

  1. 批量操作时务必使用事务
  2. 优先选择 insert_many()bulk_create() 进行大批量插入
  3. 更新操作使用原子方式避免竞态条件
  4. 根据数据库类型选择合适的 Upsert 策略

掌握这些技巧可以显著提高数据库操作效率,特别是在处理大量数据时。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郦嵘贵Just

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值