如何检查小马 orm 缓存中是否存在对象?
How do I check if object exist in pony orm cache?
我正在尝试一些数据处理,然后一次性插入,表有一些复合键,我用它来检查该 ID 的记录是否存在,然后它应该更新记录而不是创建。
在数据处理过程中,相同的 id 可能会多次出现在样本数据中,并且在处理过程中,它不会在数据库中找到与该 Id 匹配的记录,因此它每次都会尝试创建记录。
有什么方法可以检查复合键匹配的缓存吗?
您可以使用实体实例的 get
方法通过主键值的组合查找对象。
get
方法同时搜索db_session
缓存和数据库,returns None
如果没有找到对象:
from pony import orm
db = orm.Database('sqlite', ':memory:')
class Point(db.Entity):
x = orm.Required(int)
y = orm.Required(int)
description = orm.Optional(str)
orm.PrimaryKey(x, y)
db.generate_mapping(create_tables=True)
points = [(1, 2, 'foo'), (3, 4, 'bar'), (1, 2, 'baz'), (5, 6, 'qux')]
with orm.db_session:
for a, b, s in points:
point = Point.get(x=a, y=b)
if point is None:
point = Point(x=a, y=b, description=s)
get
方法也适用于辅助 composite keys。
您还可以使用 square brackets 搜索实体实例并捕获异常:
with orm.db_session:
try:
point = Point[10, 20]
except orm.ObjectNotFound:
point = Point(x=10, y=20)
更新:关于 IdentityMap 模式用法的说明
PonyORM 使用 IdentityMap 设计模式。这意味着在 db_session
中加载或创建的相同 class 的所有对象都由其主键值索引。同一个 class 的多个对象不可能在同一个 db_session
中具有相同的主键。如果使用相同的主键值多次调用 get
方法,它将 return 相同的实例:
with db_session:
a = Point.get(x=10, y=20)
b = Point.get(x=10, y=20)
assert a is b # the same object!
这同样适用于您刚刚创建一个对象然后尝试使用相同主键 get
对象的情况:Pony 将 return 您刚创建的对象:
with db_session:
a = Point.get(x=10, y=20)
if a is None:
a = Point(x=10, y=20)
# later, in the same db_session:
b = Point.get(x=10, y=20)
assert a is b # the same object, not saved yet
另一方面,如果您尝试使用相同的主键创建两个不同的对象,您将收到错误消息:
with db_session:
a = Point(x=10, y=20)
b = Point(x=10, y=20)
Traceback (most recent call last):
...
pony.orm.core.CacheIndexError: Cannot create Point: instance with primary key 10, 20 already exists
此外,如果您在不检查的情况下尝试创建一个已存在于数据库中的对象,您将得到一个错误:
with db_session:
a = Point(x=30, y=40)
with db_session:
b = Point(x=30, y=40)
Traceback (most recent call last):
...
pony.orm.core.TransactionIntegrityError: Object Point[30, 40] cannot be stored in the database. IntegrityError: UNIQUE constraint failed: Point.x, Point.y
为了避免此错误,您可以在创建新对象之前使用 get
检查对象是否存在。
我正在尝试一些数据处理,然后一次性插入,表有一些复合键,我用它来检查该 ID 的记录是否存在,然后它应该更新记录而不是创建。
在数据处理过程中,相同的 id 可能会多次出现在样本数据中,并且在处理过程中,它不会在数据库中找到与该 Id 匹配的记录,因此它每次都会尝试创建记录。
有什么方法可以检查复合键匹配的缓存吗?
您可以使用实体实例的 get
方法通过主键值的组合查找对象。
get
方法同时搜索db_session
缓存和数据库,returns None
如果没有找到对象:
from pony import orm
db = orm.Database('sqlite', ':memory:')
class Point(db.Entity):
x = orm.Required(int)
y = orm.Required(int)
description = orm.Optional(str)
orm.PrimaryKey(x, y)
db.generate_mapping(create_tables=True)
points = [(1, 2, 'foo'), (3, 4, 'bar'), (1, 2, 'baz'), (5, 6, 'qux')]
with orm.db_session:
for a, b, s in points:
point = Point.get(x=a, y=b)
if point is None:
point = Point(x=a, y=b, description=s)
get
方法也适用于辅助 composite keys。
您还可以使用 square brackets 搜索实体实例并捕获异常:
with orm.db_session:
try:
point = Point[10, 20]
except orm.ObjectNotFound:
point = Point(x=10, y=20)
更新:关于 IdentityMap 模式用法的说明
PonyORM 使用 IdentityMap 设计模式。这意味着在 db_session
中加载或创建的相同 class 的所有对象都由其主键值索引。同一个 class 的多个对象不可能在同一个 db_session
中具有相同的主键。如果使用相同的主键值多次调用 get
方法,它将 return 相同的实例:
with db_session:
a = Point.get(x=10, y=20)
b = Point.get(x=10, y=20)
assert a is b # the same object!
这同样适用于您刚刚创建一个对象然后尝试使用相同主键 get
对象的情况:Pony 将 return 您刚创建的对象:
with db_session:
a = Point.get(x=10, y=20)
if a is None:
a = Point(x=10, y=20)
# later, in the same db_session:
b = Point.get(x=10, y=20)
assert a is b # the same object, not saved yet
另一方面,如果您尝试使用相同的主键创建两个不同的对象,您将收到错误消息:
with db_session:
a = Point(x=10, y=20)
b = Point(x=10, y=20)
Traceback (most recent call last):
...
pony.orm.core.CacheIndexError: Cannot create Point: instance with primary key 10, 20 already exists
此外,如果您在不检查的情况下尝试创建一个已存在于数据库中的对象,您将得到一个错误:
with db_session:
a = Point(x=30, y=40)
with db_session:
b = Point(x=30, y=40)
Traceback (most recent call last):
...
pony.orm.core.TransactionIntegrityError: Object Point[30, 40] cannot be stored in the database. IntegrityError: UNIQUE constraint failed: Point.x, Point.y
为了避免此错误,您可以在创建新对象之前使用 get
检查对象是否存在。