11.7 通过指定标签字符串查询文章对象

    在关系数据库中有一个很重要的优势是可以得到对象之间的关系。使用SQLAlchemy的查询能力,可以得到TagPost之间的关系,并查询出所有使用同样Tag字符串的Post

    查询是会话的一个功能。这意味着已经在会话中的对象不需要从数据库中再次取出,从而节约了时间。没有包含在会话中的对象会被缓存在会话中,这样一来,在提交时所有的修改或删除操作才触发。

    为了得到所有包含了指定标签的文章,我们需要使用关联表和Post还有Tag表。我们需要使用会话中的查询方法来指定期望得到哪种类型的对象。我们将使用流畅接口来关联不同的关联表以及最终的表,其中包含了查询的列名,代码如下所示。

    for post in session.query(Post).join(assoc_post_tag).join(Tag).filter(
      Tag.phrase == "#Whitby42" ):
      print( post.blog.title, post.date, post.title, [t.phrase for t in
    post.tags] )

    session.query()方法指定我们想要的表。如果像如上代码那样来使用,我们将得到每一行记录。join()方法标识了更多需要匹配的表。由于在类定义中提供了关系信息,因此 SQLAlchemy 能够通过使用主键和外键完成行的匹配进而创建出详细的 SQL。最终的filter()方法为要得到的行的子集提供了列名。如下是生成的SQL代码。

    SELECT "POST".id AS "POSTid", "POST".title AS "POST_title", "POST".
    date AS "POST_date", "POST".rst_text AS "POST_rst_text", "POST".blog

    id AS "POSTblog_id"
    FROM "POST" JOIN "ASSOC_POST_TAG" ON "POST".id = "ASSOC_POST

    TAG"."POST_ID"
    JOIN "TAG" ON "TAG".id = "ASSOC_POST_TAG"."TAG_ID"
    WHERE "TAG".phrase = ?

    Python版本比较容易理解,因为忽略了键匹配的部分。print()函数使用post.blog. _title来完成从Post实例到相关博客的导航并显示title属性。如果博客在会话缓存中,那么导航的执行会非常快。如果博客没有在会话缓存中,就将从数据库中获取。

    相同的行为也会应用在[_t.phrase for t in post.tags]上。如果对象在会话缓存中则会取出直接用。在这种情况下,与一篇文章相关的Tag集合的SQL查询可能会如下所示。

    SELECT "TAG".id AS "TAG_id", "TAG".phrase AS "TAG_phrase"
    FROM "TAG", "ASSOC_POST_TAG"
    WHERE ? = "ASSOC_POST_TAG"."POST_ID"
    AND "TAG".id = "ASSOC_POST_TAG"."TAG_ID"

    在Python中,只需使用post.tags来进行导航。SQLAlchemy会为我们生成SQL并执行。