2017-01-16 76 views
0

我們正在將代碼庫轉換爲SqlAlchemy,其中有一個現有數據庫,我們可以修改但不能完全替換。SQLAlchemy:將信息傳遞給自動映射多對多關係

有小部件的集合,併爲每個插件,我們追蹤的20個最相似的其他部件的(這是一個方向性的關係,即widget_2可以出現在widget_1最相似的窗口小部件,而不是相反)。

  • 有一個widget表具有widget_id領域和其他一些東西。

  • 有一個​​表有first_widget_id,second_widget_idsimilarity_score。我們只保存數據庫中20個最相似的小部件,因此每個widget_id看起來都是first_widget_id的20倍。

  • first_widget_idsecond_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:%[email protected]%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其中second_widget_id == 1,其中對象EAS我們要first_widget_id == 1

+0

您能否對您的模型更具體一點?雖然您自動映射,但可能會創建一個[最小,完整且可驗證的示例](http://stackoverflow.com/help/mcve),它反映了您遇到的問題。聽起來你可能正在尋找[foreign_keys](http://docs.sqlalchemy.org/en/latest/orm/join_conditions.html)參數來處理多個連接路徑,但我無法確定。 –

+0

更新了所有相關的代碼。希望現在更清楚。 – user2449397

回答

1

您可以覆蓋similarity_collection如何連接,甚至自動映射,與explicit class definition並通過foreign_keys的關係時:

base = automap_base() 

engine = create_engine(
    'mysql://%s:%[email protected]%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) 

如果你想也控制在創建關係(S)​​- 對於整潔的關聯代理或類似 - 使用相同的模式。

+0

太棒了!我沒有意識到可以像那樣手動幫助自動映射。非常感謝! – user2449397