python - SQLalchemy 在提交之前避免在 session() 中重复
问题描述
尝试使用 session.merge() 使用 SQLalchemy 提交行时,出现重复错误。
我认为这是因为我获取数据的数据库允许列“哈希”的重复,而新的则不允许。
在提交之前,是否有一种简单的方法可以避免或删除当前会话中的重复项?
这是一个例子:
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()
谢谢
解决方案
看起来你最好在你的应用程序中“去重”:
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()
诀窍是在两者之间刷新,以便以后的合并将咨询数据库并找到现有行,但与其他解决方案相比,这将执行更多查询。
推荐阅读
- python - 通过取消堆叠我的多索引在组中设置 sort = False
- javascript - 单击一个时如何折叠其他手风琴内容?
- javascript - JavaScript 比较两个 JSON 文件并仅输出新对象
- javascript - JavaScript:无法让 .push() 命令按预期工作
- python - 在 git bash conda 环境中找不到模块
- css - 如何居中移动菜单标题文本
- oracle-apex - ORA-01756: 字符串中缺少引号- 顶点、甲骨文、PL/SQL
- javascript - 标题左侧图标不会显示 React Native
- javascript - 如果它是一个精确的数字,如何将字符串转换为浮点数,而不仅仅是以javascript中的数字开头
- ios - 在 iOS 中使用自适应卡片 sdk 解析自定义元素