Вставка связей «многие ко многим» через таблицу в SQL Alchemy - PullRequest
0 голосов
/ 28 августа 2018

Предполагая следующие модели SQL Алхимии:

likes = db.Table('likes',
    db.Column('from_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
    db.Column('to_id', db.Integer, db.ForeignKey('user.id'), primary_key=True)
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    liked_by = db.relationship('User', secondary=likes, foreign_keys=likes.c.to_id, lazy='subquery')
    likes = db.relationship('User', secondary=likes, foreign_keys=likes.c.from_id, lazy='subquery')

Какой самый быстрый и простой способ добавить множество like отношений между многими User объектами таким образом, чтобы они не потерпели неудачу при попытке создания дубликатов?

Мое ближайшее решение:

x = [
    {'from_id': 1, 'to_id': 2},
    {'from_id': 2, 'to_id': 3},
    {'from_id': 1, 'to_id': 3},
    ...
]
stmt = likes.insert().values(x)
session.execute(stmt)
session.commit()

Но вся эта транзакция завершится неудачей, если, например, 1 -> 2 уже существует. Есть ли способ выполнить этот оператор таким образом, чтобы добавить новые строки в таблицу likes и не потерпеть неудачу в существующих строках?

Решение должно быть производительным (т.е. поддерживать массовую вставку). База данных - PostgreSQL 10.x, если нужен неуниверсальный ответ.

1 Ответ

0 голосов
/ 28 августа 2018

Вы можете использовать функции "upsert", добавленные в Postgresql несколько недавно. Если вы просто хотите игнорировать дубликаты, используйте ON CONFLICT DO NOTHING :

from sqlalchemy.dialects.postgresql import insert

stmt = insert(likes).values(x).on_conflict_do_nothing()
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...