SQLalchemy Избегайте дублирования в session () перед фиксацией - PullRequest
0 голосов
/ 17 мая 2018

При попытке зафиксировать строки с помощью SQLalchemy с помощью session.merge (), я получаю ошибку дубликатов.

Я думаю, что это потому, что база данных, где я выбираю данные, позволяет дублировать столбцы "хэш" иновый - нет.

Есть ли простой способ избежать или удалить дубликаты в текущем сеансе перед фиксацией?

Вот пример:

    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 голосов
/ 18 мая 2018

Может показаться, что вам лучше "дедуплицировать" в вашем приложении:

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

Хитрость заключается в том, чтобы выполнить промежуточную очистку, чтобы последующие слияния обращались к БД и находили существующую строку, но при этом выполнялось больше запросов по сравнению с другим решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...