4

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

4

2 回答 2

5

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 问题,有助于理清概念:

在身份映射之外强制使用 sqlalchemy ORM get()

于 2015-12-17T12:46:34.700 回答
3

可以按顺序访问整个身份映射:

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

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

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

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

于 2018-02-26T11:57:53.233 回答