SQLalchemy在提交之前避免在session()中重复

时间:2018-05-17 19:14:36

标签: python mysql sqlalchemy

尝试使用session.merge()使用SQLalchemy提交行时,出现重复错误。

我认为这是因为我获取数据的数据库允许重复列“hash”而新的列不会。

在提交之前是否有一种简单的方法可以避免或删除当前会话中的重复项?

以下是一个例子:

    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.automap import automap_base
    from src.python.utils import _gen_relationship

    engine = create_engine('mysql+pymysql://{user}:{pssw}@{host}/{db}?charset=utf8'.
                               format(user=config['user'],
                                      pssw=config['password'],
                                      host=config['host'],
                                      db=config['database'])
                               )

    database = [
        {'c_hash': 'd182jd012jd102jd1', 'date': '2017-01-01', 'text': 'oijwdqoijwdqoiqwdm'},
        {'c_hash': 'apiowjdaowndoaiwjda', 'date': '2017-01-01', 'text': 'oijwdqoijwdqoiqwdm'},
        {'c_hash': 'd182jd012jd102jd1', 'date': '2017-01-02', 'text': 'adawdawdawd'}
    ]

    Base = automap_base()
    Base.prepare(engine, reflect=True, generate_relationship=_gen_relationship)

    # load necessary table information
    Mytable = Base.classes.mytable

    Session = sessionmaker(bind=engine, autoflush=False)
    session = Session()

    for row in database:
        new_row = {
            'hash': row['c_hash'],
            'date': row['date'],
            'text': row['text']
        }

        session.merge(Mytable(**new_row))
    session.commit()

谢谢

1 个答案:

答案 0 :(得分:1)

在您的应用程序中,似乎您可能会更好地“重复数据删除”:

seen = set()

# Reversed so that the last row wins.
for row in reversed(database):
    c_hash = row['c_hash']
    if c_hash not in seen:
        session.merge(Mytable(hash=c_hash,
                              date=row['date'],
                              text=row['text']))
        seen.add(c_hash)

理论上你可以让SQLAlchemy处理重复数据删除:

for row in database:
    session.merge(Mytable(hash=row['c_hash'],
                          date=row['date'],
                          text=row['text']))
    session.flush()

诀窍是在两者之间进行刷新,以便以后的合并将查询数据库并查找现有行,但与其他解决方案相比,这将执行更多查询。