我想在Elixir实体中增加(或减少)分数字段:
class Posting(Entity):
score = Field(Integer, PassiveDefault(text('0')))
def upvote(self):
self.score = self.score + 1
但是,对于upvote的并发调用,这不能可靠地工作。我能想到的最好的是这个丑陋的混乱(基本上用SQLAlchemy构造一个SQL UPDATE语句):
def upvote(self):
# sqlalchemy atomic increment; is there a cleaner way?
update = self.table.update().where(self.table.c.id==self.id)
update = update.values({Posting.score: Posting.score + 1})
update.execute()
您认为此解决方案有任何问题吗?是否有更清洁的方法来实现同样的目标?
我想避免在这里使用数据库锁。我正在使用Elixir,SQLAlchemy,Postgres。
更新
这是一个源自vonPetrushev解决方案的变体:
def upvote(self):
Posting.query.filter_by(id=self.id).update(
{Posting.score: Posting.score + 1}
)
这比我的第一个解决方案好一点,但仍需要过滤当前实体。不幸的是,如果实体分布在多个表中,这不起作用。
答案 0 :(得分:3)
我会尝试,但我不确定这是否符合您的需求:
session.query(Posting).\
.filter(Posting.id==self.id)\
.update({'score':self.score+1})
你可能想在它之后做session.commit()吗?
编辑:[关于问题的更新]
如果发布是从实体派生的,该实体是类映射到多个表,则上面的解决方案仍然有效,但Posting.id属性的含义已更改,即它不再映射到某个表的列,而是不同的构图。这里: http://docs.sqlalchemy.org/en/latest/orm/nonstandard_mappings.html#mapping-a-class-against-multiple-tables 你可以看到如何定义它。我建议它会像:
j = join(entity_table_1, entity_table_2)
mapper(Entity, j, properties={
'id': column_property(entity_table_1.c.id, entity_table_2.c.user_id)
<... some other properties ...>
})