SQLAlchemyで住所をフィルタリング: 東京、大阪、京都に住むユーザーのデータを取得
SQLAlchemy: 単一のリレーション属性を複数の値でフィルタリングする方法
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
address = Column(String)
user = relationship(User, backref='addresses')
# 例: ユーザーID 1 と 2 のユーザーの住所を取得
addresses = Address.query.filter(Address.user_id.in_([1, 2])).all()
# 例: "東京" または "大阪" に住むユーザーの住所を取得
addresses = Address.query.filter(Address.address.in_(["東京", "大阪"])).all()
解説
上記のサンプルコードでは、User
と Address
という2つのテーブルと、それらを関連付ける relationship
を定義しています。
Address.query.filter()
メソッドを使って、Address
テーブルのクエリを作成します。
Address.user_id.in_([1, 2])
という式は、user_id
属性がリスト [1, 2]
に含まれるレコードのみをフィルタリングします。
上記以外にも、in_()
以外にも、複数の値でフィルタリングを行う方法はいくつかあります。
any_()
: リスト内のいずれかの値に一致するレコードをフィルタリングします。
この解説では、SQLAlchemyを使って、単一のリレーション属性を複数の値でフィルタリングする方法について説明しました。
サンプルコードと解説を参考に、ご自身のアプリケーションで必要なフィルタリング処理を実装してください。
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
address = Column(String)
user = relationship(User, backref='addresses')
# 例: ユーザーID 1 と 2 のユーザーの住所を取得
addresses = Address.query.filter(Address.user_id.in_([1, 2])).all()
# 例: "東京" または "大阪" に住むユーザーの住所を取得
addresses = Address.query.filter(Address.address.in_(["東京", "大阪"])).all()
# 例: ユーザーID 1 と 2 のユーザーで、"東京" または "大阪" に住むユーザーの住所を取得
addresses = Address.query.filter(
Address.user_id.in_([1, 2]),
Address.address.in_(["東京", "大阪"])
).all()
# 例: ユーザー名 "John" で、"東京" に住むユーザーの住所を取得
addresses = Address.query.filter(
Address.user.name == "John",
Address.address == "東京"
).all()
さまざまな条件を組み合わせて、複数の値でフィルタリングを行うことができます。
複数の値でフィルタリングを行うその他の方法
# 例: ユーザーID 1 または 2 のユーザーの住所を取得
addresses = Address.query.filter(Address.user_id.any_([1, 2])).all()
# 例: "東京" または "大阪" または "京都" に住むユーザーの住所を取得
addresses = Address.query.filter(Address.address.any_(["東京", "大阪", "京都"])).all()
# 例: ユーザーID 1 と 2 のユーザーで、"東京" と "大阪" に住むユーザーの住所を取得
addresses = Address.query.filter(
Address.user_id.in_([1, 2]),
Address.address.all_(["東京", "大阪"])
).all()
# 例: ユーザーID 1 または 2 のユーザーの住所を取得
subquery = User.query.filter(User.id.in_([1, 2])).subquery()
addresses = Address.query.filter(Address.user_id.in_(subquery)).all()
外部結合を使って、複数の値に一致するレコードを取得することもできます。
# 例: ユーザーID 1 または 2 のユーザーの住所を取得
addresses = Address.query.outerjoin(User).filter(User.id.in_([1, 2])).all()
それぞれの方法の特徴を理解して、ご自身のアプリケーションに合った方法を選択してください。
sqlalchemy