SqlAlchemyモデルを定義しています
_from sqlalchemy.dialects.postgresql import JSONB
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
nickname = db.Column(db.String(255), nullable=False)
city = db.Column(db.String(255))
contact_list = db.Column(JSONB)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def add_user():
user = User(nickname="Mike")
user.contact_list = [{"name": "Sam", "phone": ["123456", "654321"]},
{"name": "John", "phone": ["159753"]},
{"name": "Joe", "phone": ["147889", "98741"]}]
db.session.add(user)
db.session.commit()
if __name__ == "__main__":
add_user()
_
phoneを使用してcontact_listからnameを取得するにはどうすればよいですか?たとえば、147889がありますが、どうすれば取得できますかJoe?
私はこれを試しました
User.query.filter(User.contact_list.contains({"phone": ["147889"]})).all()
しかし、それは私に空のリスト_[]
_を返します
これどうやってするの?
JSONパスに最も外側の配列も含める必要があることを忘れただけです。
User.query.filter(User.contact_list.contains([{"phone": ["147889"]}])).all()
探しているユーザーを返します。 JSONにキー「phone」などのオブジェクトが含まれている場合、元のクエリは一致します。これにより、JSON構造の特定のオブジェクト/名前ではなく、問題のUser
オブジェクトが返されることに注意してください。それが必要な場合は、最終目標のように思われるように、各ユーザーの配列要素を展開し、結果のレコードに基づいてフィルタリングし、名前を選択できます。
val = db.column('value', type_=JSONB)
db.session.query(val['name'].astext).\
select_from(User,
db.func.jsonb_array_elements(User.contact_list).alias()).\
filter(val.contains({"phone": ["147889"]})).\
all()
一方、上記のクエリは、フィルタリングする前にすべての配列を展開する必要があるため、最初のクエリほどインデックスフレンドリーではありません。そのため、連絡先リストに電話を含むユーザーを最初に見つけることが有益な場合があります。サブクエリまたはCTEを実行してから、展開してフィルタリングします。