Querying posts that are given a tag

An important benefit of a relational database is our ability to follow the relationships among the objects. Using SQLAlchemy's query capability, we can follow the relationship from Tag to Post and locate all Posts that share a given Tag.

A query is a feature of a session. This means that objects already in the session don't need to be fetched from the database, which is a potential time saver. Objects not in the session are cached in the session so that updates or deletes can be handled at the time of the commit.

To gather all of the posts that have a given tag, we need to use the intermediate association table as well as the Post and Tag tables. We'll use the query method of the session to specify what kinds of objects we expect to get back. We'll use the fluent interface to join in the various intermediate tables and the final table that we want with the selection criteria. Here's how it looks:

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

The session.query() method specifies the table that we want to see. The join() methods identify the additional tables that must be matched. Because we provided the relationship information in the class definitions, SQLAlchemy can work out the SQL details required to use primary keys and foreign keys to match rows. The final filter() method provides the selection criteria for the desired subset of rows. Here's the SQL that was generated:

SELECT "POST".id AS "POST_id", 
"POST".title AS "POST_title",
"POST".date AS "POST_date",
"POST".rst_text AS "POST_rst_text",
"POST".blog_id AS "POST_blog_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 = ?

The Python version is a bit easier to understand, as the details of the key matching can be elided. The print() function uses post.blog.title to navigate from the Post instance to the associated blog and show the title attribute. If the blog was in the session cache, this navigation is done quickly. If the blog was not in the session cache, it will be fetched from the database.

This navigation behavior applies to [t.phrase for t in post.tags] too. If the object is in the session cache, it's simply used. In this case, the collection of the Tag objects associated with a post might lead to a complex SQL query as follows:

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"

In Python, we simply navigated via post.tags. SQLAlchemy generated and executed the SQL for us.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset