是否可以使用不是来自主键的几个字段从身份映射中检索项目(之前已经获取)?比如我经常(external_id, platform_id)
成对查询一个表,它是唯一键,但不是主键。在这种情况下,我想省略不必要的 SQL 查询。
2 回答
identity_map 和 get() 的简要概述:
为 SQLAlchemy 对象的生命周期保留身份映射,session
即在 Web 服务或 RESTful api 的情况下,session
对象的生命周期不超过一个request
(推荐)。
来自:http ://martinfowler.com/eaaCatalog/identityMap.html
身份映射记录了在单个业务事务中从数据库中读取的所有对象。每当您想要一个对象时,您首先检查身份映射以查看您是否已经拥有它。
在 SQLAlchemy 的 ORM 中有这种特殊的查询方法get()
,它首先identity_map
使用 pk(仅允许的参数)并从身份映射返回对象,实际执行SQL
查询并访问数据库。
从文档:
get(ident)
根据给定的主键标识符返回一个实例,或者
None
如果没有找到。
get()
特殊之处在于它提供了对所有者身份映射的直接访问Session
。如果给定的主键标识符存在于本地标识映射中,则直接从此集合返回对象并且不发出任何 SQL,除非该对象已被标记为完全过期。如果不存在,则执行 SELECT 以定位对象。
仅get()
使用官方文档identity_map
:
它在某种程度上被用作缓存,因为它实现了
identity map
模式,并存储键控到它们的primary key
. 但是,它不执行任何类型的查询缓存。这意味着,如果您说session.query(Foo).filter_by(name='bar')
,即使Foo(name='bar')
在身份映射中就在那里,会话也不知道这一点。它必须向数据库发出 SQL,取回行,然后当它看到行中的主键时,它可以查看本地标识映射并看到对象已经存在。只有当您说query.get({some primary key})
Session 不必发出查询时。
PS如果您不使用 查询pk
,那么您一开始就没有点击identity_map
。
很少有相关的 SO 问题,有助于理清概念:
可以按顺序访问整个身份映射:
for obj in session.identity_map.values():
print(obj)
要通过任意属性获取对象,您必须先过滤对象类型,然后检查您的属性。
它不是在恒定时间内查找,但可以防止不必要的查询。
有一个论点是,对象可能已被另一个进程修改,并且身份映射不保持当前状态,但这个论点是无效的:如果您的事务隔离级别是read committed
(或更低) - 这通常是这种情况,查询完成后,数据始终可能已立即更改。