【SQLAlchemy系列】 SQLAlchemy 中的多条件查询:or*与 in*操作符
博客目录
- 一、SQLAlchemy 查询基础
- 二、or\_操作符的使用场景与实现
- 1. or\_操作符的基本概念
- 2. 典型应用场景
- 3. or\_操作符的优势
- 4. 高级用法
- 三、in\_操作符的简洁替代方案
- 1. in\_操作符简介
- 2. 使用示例
- 3. in\_操作符的优势
- 4. 注意事项
- 四、or*与 in*的性能比较
- 五、实际应用中的最佳实践
- 六、其他相关操作符
- 七、复杂查询示例
在现代 Web 应用开发中,数据库查询是不可或缺的核心功能。SQLAlchemy 作为 Python 中最流行的 ORM 工具之一,提供了强大而灵活的查询接口。
一、SQLAlchemy 查询基础
SQLAlchemy 的查询构建基于其强大的表达式语言,允许开发者以 Pythonic 的方式构建复杂的 SQL 查询。基本的查询结构通常包括session.query()
方法配合filter()
方法使用,后者用于添加各种条件限制。
例如,一个简单的查询可能如下:
from models import ProviderModel# 查询所有配置不为空的ProviderModel记录
records = db.session.query(ProviderModel).filter(ProviderModel.encrypted_config.isnot(None)
).all()
在实际业务场景中,我们经常需要更复杂的查询条件,特别是当某个字段需要匹配多个可能值时。这时就需要引入逻辑操作符来构建复合条件。
二、or_操作符的使用场景与实现
1. or_操作符的基本概念
SQLAlchemy 的or_
操作符用于实现逻辑"或"运算,允许查询满足多个条件中至少一个的记录。它对应于 SQL 中的 OR 关键字,但在 SQLAlchemy 中以函数式的方式使用。
2. 典型应用场景
在文章开头提到的例子中,我们需要查询model_type
字段值为’text-generation’或’embeddings’的记录。使用or_
操作符的解决方案如下:
from sqlalchemy import or_provider_models = db.session.query(ProviderModel).filter(ProviderModel.encrypted_config.isnot(None),ProviderModel.provider_name != 'openai',or_(ProviderModel.model_type == 'text-generation',ProviderModel.model_type == 'embeddings'),ProviderModel.conf_type == '0'
).all()
3. or_操作符的优势
- 明确性:清晰地表达了"或"逻辑关系,代码可读性强
- 灵活性:可以组合任意数量和类型的条件
- 可扩展性:可以与其他逻辑操作符(如
and_
,not_
)嵌套使用
4. 高级用法
or_
操作符可以嵌套使用,构建更复杂的逻辑:
from sqlalchemy import and_, or_# 更复杂的条件组合
query = db.session.query(ProviderModel).filter(or_(and_(ProviderModel.model_type == 'text-generation',ProviderModel.provider_name.like('%ai%')),and_(ProviderModel.model_type == 'embeddings',ProviderModel.conf_type.in_(['0', '1'])))
)
三、in_操作符的简洁替代方案
1. in_操作符简介
当需要检查字段值是否存在于一个预定义的集合中时,in_
操作符提供了更简洁的语法。它对应于 SQL 中的 IN 关键字。
2. 使用示例
同样的查询需求可以用in_
操作符更简洁地表达:
provider_models = db.session.query(ProviderModel).filter(ProviderModel.encrypted_config.isnot(None),ProviderModel.provider_name != 'openai',ProviderModel.model_type.in_(['text-generation', 'embeddings']),ProviderModel.conf_type == '0'
).all()
3. in_操作符的优势
- 简洁性:代码更短,更易读
- 性能:数据库通常对 IN 操作有优化
- 可维护性:当需要添加更多匹配值时,只需扩展列表
4. 注意事项
- 对于非常大的值列表(如上千个),IN 查询可能性能不佳
- 某些数据库对 IN 列表的长度有限制
- 对于 NULL 值的处理需要特别注意
四、or与 in的性能比较
在实际应用中,or_
和in_
在功能上是等价的,但性能表现可能有所不同:
- 小规模数据:两者性能差异不大
- 大规模数据:
in_
通常更高效,特别是当数据库能够使用索引时 - 执行计划:不同数据库可能对这两种写法生成不同的执行计划
建议在实际应用中通过 EXPLAIN 分析两种写法的执行计划,选择最优方案。
五、实际应用中的最佳实践
- 代码可读性优先:对于少量选项(2-3 个),
or_
可能更清晰;对于更多选项,in_
更合适 - 动态条件构建:当条件需要动态生成时,
in_
通常更方便 - 混合使用:复杂查询中可以混合使用两种方式
- 测试验证:始终验证生成的 SQL 是否符合预期
# 动态构建查询条件的例子
allowed_types = get_allowed_model_types() # 返回['text-generation', 'embeddings', ...]query = db.session.query(ProviderModel).filter(ProviderModel.model_type.in_(allowed_types)
)
六、其他相关操作符
除了or_
和in_
,SQLAlchemy 还提供了其他有用的操作符:
- and_:逻辑"与"(通常用逗号隐式表示)
- not_:逻辑"非"
- like/ilike:模式匹配
- between:范围查询
- is_null/isnot_null:NULL 值检查
七、复杂查询示例
结合多种操作符的复杂查询示例:
from sqlalchemy import and_, or_, not_query = db.session.query(ProviderModel).filter(ProviderModel.encrypted_config.isnot(None),or_(and_(ProviderModel.provider_name != 'openai',ProviderModel.model_type.in_(['text-generation', 'embeddings'])),and_(ProviderModel.provider_name == 'special',not_(ProviderModel.model_type == 'deprecated'))),ProviderModel.conf_type == '0'
).order_by(ProviderModel.created_at.desc())
觉得有用的话点个赞
👍🏻
呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙