[英]SQLAlchemy: create many-to-many and populate association
我的想法如下:
Documents
),其中包含一些文本,例如博客文章。 每個文檔都有一個唯一的 id text_id
。Links
) 存儲出現在這些帖子中的唯一 url。 每個 url 都有一個唯一的 id url_id
。Association
) 綁定,關聯表將文本的 id 映射到域的 id。我希望能夠獲取帖子,從中收集網址,然后:
Documents
中創建新記錄Links
並通過Association
與文檔相關對於初學者,我創建了三個類,如下所示:
class Association(Base):
__tablename__ = 'association'
text_id = Column('text_id', Integer, ForeignKey('left.text_id'), primary_key=True)
url_id = Column('url_id', Integer, ForeignKey('right.url_id'), primary_key = True)
child = relationship("Links", back_populates='parents')
parent = relationship("Documents", back_populates='children')
class Documents(Base):
__tablename__ = 'left'
text_id = Column(Integer, primary_key=True, unique=True)
text = Column(Text)
children = relationship("Association", back_populates='parent')
class Links(Base):
__tablename__ = 'right'
url_id = Column(Integer, primary_key=True, autoincrement=True, unique=True)
url = Column(Text, unique=True)
parents = relationship('Association', back_populates = 'child')
Base.metadata.create_all(engine)
然后我試圖加載數據:
data = [
{'id':1, 'text':'sometext', 'url':'facebook.com'},
{'id':2, 'text':'sometext', 'url':'twitter.com'},
{'id':3, 'text':'sometext', 'url':'twitter.com'}
]
for row in data:
d = Document(text_id = row['id'])
a = Association()
a.child = Links(url = row['url'])
d.children.append(a)
session.add(d)
session.commit()
這會導致錯誤:
Traceback (most recent call last):
File "/home/user/.pyenv/versions/3.7.12/envs/myenv/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3444, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-13-325b1cd57576>", line 5, in <module>
p.children.append(a)
File "/home/user/.pyenv/versions/3.7.12/envs/myenv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 1240, in __getattr__
return self._fallback_getattr(key)
File "/home/user/.pyenv/versions/3.7.12/envs/myenv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 1214, in _fallback_getattr
raise AttributeError(key)
AttributeError: append
我真的不明白為什么,因為似乎我已經按照官方文檔的建議做了所有事情。
另一方面,即使這樣可行,我懷疑通過p.children.append(a)
附加已經存在的 url 可能會導致錯誤,因為它實際上會嘗試創建副本,而Links
不允許這樣做。
如果這很重要,我正在使用 mySQL 和 MariaDB。
也許我為這項工作選擇了錯誤的工具 - 如果您能提出替代方案,我將不勝感激。
UPD:我無法插入,因為我使用automap_base()
而不是declarative_base()
實例化了一個基礎。 現在我可以 append,但是,重復的條目確實是一個問題:
sqlalchemy.exc.IntegrityError: (pymysql.err.IntegrityError) (1062, "Duplicate entry 'twitter.com' for key 'url'")
[SQL: INSERT INTO `right` (url) VALUES (%(url)s)]
[parameters: {'url': 'twitter.com'}]
(Background on this error at: https://sqlalche.me/e/14/gkpj)
首先,如果您使用正確的域名而不是: right
, left
, child
, children
會更容易調試。 我知道這是文檔的副本,但是文檔是通用的,而您的案例是特定的。 您的代碼將更具可讀性。
為避免重復,您應該在插入該記錄之前檢查已經存在( Documents
具有唯一的text_id
, Links
具有唯一的url
)。
for row in data:
d = session.query(Document).filter_by(text_id=row['id']).first()
if not d:
d = Document(text_id=row['id'])
link = session.query(Links).filter_by(url=row['url']).first():
if not link:
link = Links(url=row['url'])
a = Association(child=link)
d.children.append(a)
session.add(d)
session.flush()
session.commit()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.