我是SQLAlchemy ORM的新手,我正努力在多個表上完成複雜的查詢 - 我發現在Doctrine DQL中執行相對簡單的查詢。如何在SQLAlchemy中查詢多個表ORM
我有屬於國家的城市的數據對象。一些城市也有一個縣的ID設置,但不是全部。除了必要的主鍵和外鍵以外,每條記錄還有一個text_string_id,它鏈接到用不同語言存儲城市/縣/國家名稱的TextStrings表。該TextStrings MySQL表看起來是這樣的:
CREATE TABLE IF NOT EXISTS `text_strings` (
`id` INT UNSIGNED NOT NULL,
`language` VARCHAR(2) NOT NULL,
`text_string` varchar(255) NOT NULL,
PRIMARY KEY (`id`, `language`)
)
我想構建一個麪包屑爲每個城市,下面的形式:
country_en_name> city_en_name OR
country_en_name> county_en_name> city_en_name,
取決於是否爲該城市設置了縣屬性。在學說這將是相對簡單的:
$query = Doctrine_Query::create()
->select('ci.id, CONCAT(cyts.text_string, \'> \', IF(cots.text_string is not null, CONCAT(cots.text_string, \'> \', \'\'), cits.text_string) as city_breadcrumb')
->from('City ci')
->leftJoin('ci.TextString cits')
->leftJoin('ci.Country cy')
->leftJoin('cy.TextString cyts')
->leftJoin('ci.County co')
->leftJoin('co.TextString cots')
->where('cits.language = ?', 'en')
->andWhere('cyts.language = ?', 'en')
->andWhere('(cots.language = ? OR cots.language is null)', 'en');
與SQLAlchemy ORM,我努力實現同樣的事情。我相信我正確地已經設置的對象 - 形式如:
class City(Base):
__tablename__ = "cities"
id = Column(Integer, primary_key=True)
country_id = Column(Integer, ForeignKey('countries.id'))
text_string_id = Column(Integer, ForeignKey('text_strings.id'))
county_id = Column(Integer, ForeignKey('counties.id'))
text_strings = relation(TextString, backref=backref('cards', order_by=id))
country = relation(Country, backref=backref('countries', order_by=id))
county = relation(County, backref=backref('counties', order_by=id))
我的問題是在查詢 - 我已經試過各種方法來產生的痕跡,但似乎沒有任何工作。一些觀察:
也許在查詢中使用像CONCAT和IF這樣的東西並不是很pythonic(它甚至可以用ORM嗎?) - 所以我嘗試在SQLAlchemy之外的Python循環中執行這些操作記錄。然而,在這裏我一直在努力訪問各個領域 - 例如,模型訪問器似乎並不深入n層,例如, City.counties.text_strings.language不存在。
我也使用元組實驗 - 我得給它的工作最接近的是通過拆分出來到兩個查詢:
# For cities without a county
for city, country in session.query(City, Country).\
filter(Country.id == City.country_id).\
filter(City.county_id == None).all():
if city.text_strings.language == 'en':
# etc
# For cities with a county
for city, county, country in session.query(City, County, Country).\
filter(and_(City.county_id == County.id, City.country_id == Country.id)).all():
if city.text_strings.language == 'en':
# etc
我把它分解出到兩個查詢,因爲我不能弄清楚如何在一個查詢中使西裝加入可選。但是這種方法當然是可怕的,而且更糟的是第二個查詢不能100%工作 - 它沒有加入所有不同的city.text_strings以進行後續過濾。
所以我很難倒!你可以給我任何幫助,讓我在SQLAlchemy ORM中執行這些複雜ISH查詢的正確途徑,我將非常感激。
巨大的感謝邁克爲這個答案 - 我應該知道使用別名!一旦我將SQLAlchemy升級到更新的版本,您的代碼就可以正常工作。最後,我修改了你的代碼 - 我將在下面粘貼我的代碼作爲單獨的答案,以防有人想看到它。最後一點:你說,「我認爲它只是簡單地說:city.text_strings.text_string ...」我試着做這樣的事情,但是這種語法似乎並不尊重外部聯盟 - 即text_string屬性用於語言=='de'而不是語言=='en'。我不確定我做錯了什麼! – 2011-01-16 13:27:31