我们正在将代码库转换为SqlAlchemy,其中存在一个我们可以修改但不能完全替换的现有数据库。
有一组小部件,每个小部件我们跟踪20个最相似的小部件(这是一个方向性关系,即widget_2
可以出现在widget_1
最相似的小部件中,但反之亦然。)
有一个widget
表,其中包含widget_id
字段和其他一些内容。
有一个similarity
表,其中包含first_widget_id
,second_widget_id
和similarity_score
。我们只在数据库中保存了20个最相似的小部件,因此每个widget_id
只显示first_widget_id
的20倍。
first_widget_id
和second_widget_id
的外键指向widget
表。我们正在使用SQLAlchemy的自动化功能,因此Widget
对象具有Widget.similarity_collection
字段。但是,对于指定的widget_id
,它只包含second_widget_id == widget_id
的项目,而我们需要first_widget_id == widget_id
。据我所知,SQLAlchemy无法知道它应该选择哪一个。
我们能以某种方式告诉它吗?
编辑:根据评论,以下是模型的更多细节:
CREATE TABLE IF NOT EXISTS `similarity` (
`first_widget_id` int(6) NOT NULL,
`second_widget_id` int(6) NOT NULL,
`score` int(5) NOT NULL,
PRIMARY KEY (`first_widget_id`,`second_widget_id`),
KEY `first_widget_id` (`first_widget_id`),
KEY `second_widget_id_index` (`second_widget_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `similarity`
ADD CONSTRAINT `similar_first_widget_id_to_widgets_foreign_key` FOREIGN KEY (`first_widget_id`) REFERENCES `widgets` (`widget_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `similar_second_widget_id_to_widgets_foreign_key` FOREIGN KEY (`second_widget_id`) REFERENCES `widgets` (`widget_id`) ON DELETE CASCADE ON UPDATE CASCADE;
CREATE TABLE IF NOT EXISTS `widgets` (
`widget_id` int(6) NOT NULL AUTO_INCREMENT,
`widget_name` varchar(70) NOT NULL,
PRIMARY KEY (`game_id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=13179 ;
使用此python代码初始化SQLAlchemy:
base = automap_base()
engine = create_engine(
'mysql://%s:%s@%s/%s?charset=utf8mb4' % (
config.DB_USER, config.DB_PASSWD, config.DB_HOST, config.DB_NAME
), echo=False
)
# reflect the tables
base.prepare(self.engine, reflect=True)
Widgets = base.classes.widgets
现在当我们做类似的事情时:
session.query(Widgets).filter_by(widget_id=1).similarity_collection
我们获得了sqlalchemy.ext.automap.similar
的{{1}}个对象,而我们想要second_widget_id == 1
答案 0 :(得分:1)
您可以覆盖similarity_collection
加入explicit class definition并将foreign_keys
传递给关系的方式,即使在自动加入时也是如此:
base = automap_base()
engine = create_engine(
'mysql://%s:%s@%s/%s?charset=utf8mb4' % (
config.DB_USER, config.DB_PASSWD, config.DB_HOST, config.DB_NAME
), echo=False
)
# The class definition that ensures certain join path for the relationship.
# Rest of the mapping is automapped upon reflecting.
class Widgets(base):
__tablename__ = 'widgets'
similarity_collection = relationship(
'similarity', foreign_keys='similarity.first_widget_id')
base.prepare(self.engine, reflect=True)
如果您还希望控制similarity
中创建的关系 - 对于整洁的关联代理等 - 使用相同的模式。