我是SQLAlchemy ORM的新手,我正努力在多个表上完成复杂的ish查询,我发现在Doctrine DQL中可以相对简单地完成这些查询。
我有城市的数据对象,属于国家。有些城市也有县的身份证,但不是全部。除了必要的主键和外键之外,每条记录还具有一个文本字符串id,它链接到一个文本字符串表,该表以不同的语言存储城市/县/国家的名称。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`)
)
我想为每个城市构建一个面包屑,形式如下:
国家名称>;城市名称或
国家名称>;县名称>;城市名称
取决于是否为此城市设置了县属性。在理论上,这是相对简单的:
$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 inline之类的东西不是很pythonic(在ORM中甚至是可能的吗?)-所以我尝试在SQLAlchemy之外,在记录的Python循环中执行这些操作。然而,在这里,我很难访问各个字段——例如,模型访问器似乎没有深入到n层,例如City.countries.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
我把它分成两个查询,因为我不知道如何在一个查询中使Suit join成为可选的。但是这种方法当然很糟糕,更糟糕的是第二个查询没有100%工作——它没有连接所有不同的city.text_字符串以进行后续过滤。
所以我被难住了!如果您能帮助我在SQLAlchemy ORM中设置正确的路径来执行这些复杂的ish查询,我将不胜感激。
为了记录,这里是我最后使用的代码。迈克(zzzeek)的回答仍然是正确和确定的,因为这只是他的一个改编,这是我的突破。
Suit
的映射不存在,但基于推进查询,我假设它有一个text_strings
属性。SQLAlchemy文档中描述连接别名的相关部分位于:
http://www.sqlalchemy.org/docs/orm/tutorial.html#using-aliases
函数的生成位于:
http://www.sqlalchemy.org/docs/core/tutorial.html#functions
不过,我觉得说起来简单得多:
如果你在城市上加上一个描述符,就可以:
然后你可以说
city.text_string
。相关问题 更多 >
编程相关推荐