SQLAlchemy:返回两个给定记录共享的关联记录列表

时间:2014-04-21 20:51:55

标签: python sql python-2.7 sqlalchemy rdbms

想知道是否/如何使用SQLAlchemy返回两个博客帖子之间共享的标签列表,或者我是否需要单独拉出每个标签并在Python端进行比较。以此为例(借鉴SQLAlchemy how to filter by children in many to many):

import sqlalchemy as alc
Session = alc.sessionmaker(bind=engine)
session = Session()
Base = alc.declarative_base(bind=engine)

class Tag(Base):
    __tablename__ = 'tags'
    id = alc.Column(alc.Integer, primary_key=True)
    name = alc.Column(alc.String)
    def __repr__(self): 
        return '<Tag "%s">' % self.name

class Post(Base):
    __tablename__ = 'posts'
    id = alc.Column(alc.Integer, primary_key=True)
    text = alc.Column(alc.String)
    def __repr__(self): 
        return '<Post id %d>' % self.id


class PostTag(Base):
    __tablename__ = 'post_tags'
    post_id = alc.Column(alc.Integer, alc.ForeignKey('posts.id'), primary_key=True)
    tag_id = alc.Column(alc.Integer, alc.ForeignKey('tags.id'), primary_key=True)
    post = alc.relationship("Post", backref="ptags")
    tag = alc.relationship("Tag", backref="tposts")
    tagging_user_name = alc.Column(alc.String)

我试图弄清楚如何构建一个查询,给定两个帖子,将返回两者共享的标签列表。例如,如果我们将post_1与标签&#34;食谱&#34;,&#34;来宾&#34;,&#34;视频&#34;和&#34;素食&#34;和post_2与标签&#34;食谱&#34;,&#34;音频&#34;,&#34;甜点&#34;,&#34;素食&#34;,我想要一个返回[<Tag "recipe">, <Tag "vegetarian">]的查询。< / p>

我已经想通了:

session.query(Post).join(PostTag).filter(PostTag.tag.has(name='joke')).all()

将返回标记为&#34;笑话&#34;在列表中,但我不知道如何找到我可能希望从tags表开始的预感之外的两个帖子之间共享的标签列表。任何帮助将非常感激。

1 个答案:

答案 0 :(得分:2)

这对我有用:

from sqlalchemy.sql import exists, and_

pt1 = exists().where(and_(PostTag.tag_id == Tag.id, PostTag.post_id == id1))
pt2 = exists().where(and_(PostTag.tag_id == Tag.id, PostTag.post_id == id2))
tags = session.query(Tag.name).filter(pt1, pt2).all()

应该生成类似于以下内容的SQL:

SELECT name FROM tags
WHERE EXISTS(SELECT 1 FROM post_tags WHERE tag_id=id AND post_id=<post id 1>)
AND EXISTS(SELECT 1 FROM post_tags WHERE tag_id=id AND post_id=<post id 2>)