【问题标题】:Need help with joins in sqlalchemy需要有关 sqlalchemy 中的连接的帮助
【发布时间】:2010-12-22 03:50:19
【问题描述】:

我是 Python 以及 SQL Alchemy 的新手,但不是底层开发和数据库概念。我知道我想做什么以及如何手动完成,但我正在尝试了解 ORM 的工作原理。

我有两个表格,图片和关键字。 Images 表包含一个作为其主键的 id 列,以及一些其他元数据。关键字表仅包含一个 id 列(Images 的外键)和一个关键字列。我正在尝试使用声明性语法正确声明这种关系,我认为我做得正确。

Base = declarative_base()

class Keyword(Base):
    __tablename__ = 'Keywords'
    __table_args__ = {'mysql_engine' : 'InnoDB'}

    id = Column(Integer, ForeignKey('Images.id', ondelete='CASCADE'),
            primary_key=True)
    keyword = Column(String(32), primary_key=True)

class Image(Base):
    __tablename__ = 'Images'
    __table_args__ = {'mysql_engine' : 'InnoDB'}

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(256), nullable=False)
    keywords = relationship(Keyword, backref='image')

这代表了多对多的关系。一张图片可以有很多关键词,一个关键词可以关联很多图片。

我想对我的图片进行关键字搜索。我试过以下没有运气。

从概念上讲,这会很好,但我明白为什么它不起作用。

image = session.query(Image).filter(Image.keywords.contains('boy'))

我不断收到关于没有外键关系的错误,这对我来说似乎很明确。我看到了一些关于确保我获得正确的“加入”的信息,并且我正在使用“来自 sqlalchemy.orm 导入加入”,但仍然没有运气。

image = session.query(Image).select_from(join(Image, Keyword)).\
        filter(Keyword.keyword == 'boy')

我在查询中添加了特定的连接子句来帮助它,但据我了解,我不应该这样做。

image = session.query(Image).select_from(join(Image, Keyword,
    Image.id==Keyword.id)).filter(Keyword.keyword == 'boy')

所以最后我改变了策略,尝试查询关键字,然后使用反向引用。但是,当我尝试使用 '.images' 迭代结果时,我收到一个错误,即 'image' 属性不存在,即使我确实将其声明为 backref。

result = session.query(Keyword).filter(Keyword.keyword == 'boy').all()

我希望能够在一组关键字上查询一组独特的图像匹配项。我只是无法猜出我的语法方式,我花了几天时间阅读 SQL Alchemy 文档,试图自己解决这个问题。

我非常感谢任何能指出我所缺少的东西的人。

【问题讨论】:

    标签: python join sqlalchemy


    【解决方案1】:

    看来我仍然得到了错误的 join 版本,甚至导入了 sqlalchemy.orm 下的那个。我这样做是为了解决问题:

    from sqlalchemy.orm.util import join as join_
    
    image = session.query(Image).select_from(join_(Image, Keyword)).\
        filter(Keyword.keyword == 'boy')
    

    这真的是“最正确”的解决方案,还是我错过了 Python 的一些细微差别?由于我仍在学习,我想按照有更多经验的人的建议,以“最正确”的方式做事。谢谢。

    【讨论】:

    • join_ 不是必需的,因为在选择Keyword 实体时,根据为image 属性定义的关系,相关的Image 实体将与它一起检索。我已经尝试过了,它可以工作:[k.image.name for k in session.query(Keyword).filter_by(keyword='boy').all()]
    • 但是,如果您执行session.query(Image),您确实需要join_。但是在您的模型中,查询Keyword 实体(只有一张图像)比查询Image 实体(有很多关键字)更容易。事实上,在“正常形式”的多对多关系中,您将有另一个关键字表和一个中间关系表,其中包含关键字和图像表的外键。但在这种情况下,这两个表是相同的,因为除了字符串之外,关键字不需要任何属性。 (所以在我看来,无论如何,这是一个很好的关系设计。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多