怎么办单位递增/递减与灵药/ SQLAlchemy的

问题描述:

我想递增(或递减)的得分场在药剂实体:怎么办单位递增/递减与灵药/ SQLAlchemy的

class Posting(Entity): 

    score = Field(Integer, PassiveDefault(text('0'))) 

    def upvote(self): 
     self.score = self.score + 1 

然而,这并不可靠地与并发呼叫工作去注册。我能想出的最好的是这个丑陋的烂摊子(基本构建SQL UPDATE语句的SQLAlchemy):

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} 
    ) 

这是比我的第一个解决方案有所更好,但仍然需要过滤当前实体。不幸的是,如果实体分散在多个表中,这不起作用。

我会尽力,但我不知道这是否符合你的需求:session.commit()后右

session.query(Posting).\ 
    .filter(Posting.id==self.id)\ 
    .update({'score':self.score+1}) 

你可能想干什么?

EDIT:[有关的问题的更新]

如果过帐从实体被映射到多个表类派生,上面仍然有效的解决方案,但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 ...> 
    }) 
+2

这不是原子操作,在查询执行之前得分可能已经更新。 – 2012-09-06 17:08:34