SQLAlchemy不仅通过主键从身份映射中获取项目

时间:2015-11-27 13:46:10

标签: python orm sqlalchemy identity-map

是否可以使用不是来自主键的几个字段来从身份映射中检索项目(之前已经提取过)?例如,我经常通过(external_id, platform_id)对查询表,这是一个唯一键,但不是主键。在这种情况下,我想省略不必要的SQL查询。

2 个答案:

答案 0 :(得分:3)

identity_map和get()的简要概述:

在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问题,有助于明确这个概念:

Forcing a sqlalchemy ORM get() outside identity map

答案 1 :(得分:1)

可以按顺序访问整个身份地图:

for obj in session.identity_map.values():
    print(obj)

要通过任意属性获取对象,您必须先筛选对象类型,然后检查属性。

它不是在常量时间内查找,但可以防止不必要的查询。

有一个论点,即对象可能已被另一个进程修改,并且身份映射不保持当前状态,但此参数无效:如果您的事务隔离级别为read committed(或通常情况下,数据总是可能在查询完成后立即更改。