web-dev-qa-db-ja.com

sqlalchemy、子列値の逆包含(含まない)リストを使用して選択

Flask-sqlalchemyに典型的な投稿/タグ(1つの投稿に関連付けられた多くのタグ)関係があり、提供するリストでタグが付けられていない投稿を選択したいと思います。まず、私が設定したモデル:

_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を使用してこれをどのように達成しますか?

21
bazaars

否定 any を使用するのはかなり簡単です:

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

これを簡単に試してください:

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

お役に立てれば!

14
aIKid

厄介な解決策を考えましたが、とりあえずうまくいきます。誰かがもっと賢い方法を思いついたら聞いてみたいです。

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))
3
bazaars

notin _ は私のために機能し、調整された

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