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