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}")