SQLAlchemy 2.0 关系运算符 any 与 has 方法的使用

本文介绍了SQLAlchemyORM中的any()和has()方法,用于处理一对多和多对一关系的查询,演示了如何使用这两个方法在Pythonic风格下执行复杂的SQL查询逻辑,包括示例和注意事项。
摘要由CSDN通过智能技术生成

any 方法

在 SQLAlchemy 中,any() 方法是一个特殊的查询构造器,用于一对多或多对一的关系中。它用于创建一个 SQL 表达式,该表达式检查在一对多关系中,至少有一个子记录满足指定的条件。当 any() 应用于关系属性时,它生成一个 SQL EXISTS 子句。这对于实现某些类型的查询非常有用,特别是当你需要筛选出至少有一个满足特定条件子项的父项时。

例如,假设有一个 User 类和一个 Address 类,在它们之间存在一对多的关系(一个用户可以有多个地址)。如果你想查询所有至少有一个地址在特定城市的用户,你可以这样写:

# 查询所有至少有一个地址在 "SomeCity" 的用户
stmt = select(User).where(User.addresses.any(Address.city == "SomeCity"))

在这个例子中,User.addresses.any(Address.city == “SomeCity”) 创建了一个 SQL 表达式,当 User 对象的 addresses 集合中至少有一个 Address 对象的 city 属性等于 “SomeCity” 时,这个表达式的值为真。这是一个非常强大的特性,因为它允许你使用 Pythonic 的方式表达复杂的 SQL 查询逻辑。

has 方法

在 SQLAlchemy ORM(对象关系映射)框架中,has() 方法是用于多对一关系查询的一个函数。当你在模型中定义了一个多对一的关系时(例如,一个子项属于一个父项),has() 方法可以用于构造一个查询,这个查询检查这种关系是否满足特定的条件。

具体来说,当你调用 has() 方法时,它将创建一个 SQL 表达式,这个表达式在关联对象满足给定的条件时为真。这通常用于构造 WHERE 子句中的条件,特别是在处理多对一关系时。

例如,假设有一个 Address 类和一个 User 类,在它们之间存在多对一的关系(一个地址属于一个用户)。如果你想查询所有属于特定用户名的地址,你可以这样写:

# 查询所有属于名为 "SomeUser" 的用户的地址
stmt = select(Address).where(Address.user.has(User.name == "SomeUser"))

在这个例子中,Address.user.has(User.name == “SomeUser”) 创建了一个 SQL 表达式,当 Address 对象的 user 关联对象的 name 属性等于 “SomeUser” 时,这个表达式的值为真。这是一个非常实用的功能,因为它使得能够使用 Pythonic 的方式来表达复杂的 SQL 查询逻辑,特别是在处理涉及关系的查询时。

代码示例

async def relationship_where_operations_any(self):
    """
    关系运算符操作:any 方法使用示例
    官方文档: https://docs.sqlalchemy.org/en/20/orm/queryguide/select.html#relationship-where-operators

    any 方法用于一对多关系中,允许在 any 方法中指定一个条件,该条件会生成一个 SQL 表达式,只有满足该条件的元素才会被查询出来。
    :return:
    """
    print("==============================any 方法使用案例1=========================================")
    # 用户表(models.VadminUser)与 部门表(VadminDept)为多对多关系
    # 查找出只有满足关联了部门名称为 "人事一部" 的所有用户,没有关联的则不会查询出来
    sql1 = select(models.VadminUser).where(models.VadminUser.depts.any(models.VadminDept.name == "人事一部"))
    queryset1 = await self.db.scalars(sql1)
    result1 = queryset1.unique().all()
    for data in result1:
        print(f"用户编号:{data.id} 用户名称:{data.name}")

    print("==============================any 方法使用案例2=========================================")
    # 案例1 取反,查找出只有满足没有关联了部门名称为 "人事一部" 的所有用户,关联的则不会查询出来
    sql2 = select(models.VadminUser).where(~models.VadminUser.depts.any(models.VadminDept.name == "人事一部"))
    queryset2 = await self.db.scalars(sql2)
    result2 = queryset2.unique().all()
    for data in result2:
        print(f"用户编号:{data.id} 用户名称:{data.name}")

    print("==============================any 方法使用案例3=========================================")
    # 查询出没有关联部门的所有用户
    sql3 = select(models.VadminUser).where(~models.VadminUser.depts.any())
    queryset3 = await self.db.scalars(sql3)
    result3 = queryset3.unique().all()
    for data in result3:
        print(f"用户编号:{data.id} 用户名称:{data.name}")

async def relationship_where_operations_has(self):
    """
    关系运算符操作: has 方法使用示例
    官方文档: https://docs.sqlalchemy.org/en/20/orm/queryguide/select.html#relationship-where-operators

    has 方法用于多对一关系中,与 any 方法使用方式同理,只有满足条件的元素才会被查询出来。

    对多关系中使用 has 方法会报错,报错内容如下:
    sqlalchemy.exc.InvalidRequestError: 'has()' not implemented for collections.  Use any().
    :return:
    """
    print("==============================has 方法使用案例1=========================================")
    # 用户(models.VadminUser)与 会员卡(models.VadminVIP)为多对一关系
    # 查找出只有满足关联了会员名称为 "尊享卡" 的所有用户,没有关联的则不会查询出来
    sql1 = select(models.VadminUser).where(models.VadminUser.vip.has(models.VadminVIP.name == "尊享卡"))
    queryset1 = await self.db.scalars(sql1)
    result1 = queryset1.unique().all()
    for data in result1:
        print(f"用户编号:{data.id} 用户名称:{data.name}")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值