sqlalchemy,使用反向包含(不在)子列值列表中进行选择

Posted

技术标签:

【中文标题】sqlalchemy,使用反向包含(不在)子列值列表中进行选择【英文标题】:sqlalchemy, select using reverse-inclusive (not in) list of child column values 【发布时间】:2013-11-18 23:57:46 【问题描述】:

我在flask-sqlalchemy 中有一个典型的帖子/标签(许多标签与一个帖子相关联)关系,我想在我提供的列表中选择没有任何标签标记的帖子。一、我设置的模型:

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', lazy='dynamic')

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text(50))
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))

有点像

db.session.query(Post).filter(Post.tags.name.notin_(['dont','want','these']))

失败

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Post.tags has an attribute 'name'

我认为这是因为标签是一种关系而不是一列。当我手动编写实际的 SQL 时,我在另一个项目上工作。这是有效的 SQL:

SELECT * FROM $posts WHERE id NOT IN (SELECT post_id FROM $tags WHERE name IN ('dont','want','these'))

如何使用 sqlalchemy API 实现这一点?

【问题讨论】:

【参考方案1】:

使用否定的any 非常简单:

query = session.query(Post).filter(~Post.tags.any(Tag.name.in_(['dont', 'want', 'these'])))

【讨论】:

你先生,是救命稻草! 在v1.4中,还需要否定关系子查询 如果我想要所有没有任何标签的帖子,查询会是什么? @bhattraideb: session.query(Post).filter(~Post.tags.any())【参考方案2】:

试试这个,很简单:

users = session.query(Post).filter(not_(Post.tags.name.in_(['dont', 'want', these'])))

希望这会有所帮助!

【讨论】:

嗯,我得到了与我原来的帖子中详述的相同的错误。意思是 Post.tags 没有属性“名称”。【参考方案3】:

notin_ 适合我,调整后的示例

db.session.query(Post).filter(Post.tags.notin_(['dont','want','these'])) 

【讨论】:

【参考方案4】:

我想出了一个令人讨厌的解决方案,但它暂时有效。我很想知道是否有人提出了更智能的方法。

ignore_ids = [item.post_id for item in Tag.query.filter(Tag.name.in_(['dont','want','these'])).all()]
Post.query.filter(Post.id.notin_(ignore_ids))

【讨论】:

以上是关于sqlalchemy,使用反向包含(不在)子列值列表中进行选择的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy列值基于另一个

为啥在提交对象之前 SQLAlchemy 默认列值不可用?

PostgreSQL 反向 LIKE

如何在 SQL 中加入包含祖父-父-子列的表?

sqlalchemy中sql LIKE的反向版本[重复]

如何创建包含范围内但不在索引中的日期的 MultiIndex 的笛卡尔积