How to query JSON Array in Postgres with SqlAlchemy?

我怕爱的太早我们不能终老 提交于 2019-12-19 03:24:08

问题


I have a SqlAlchemy model defined

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()

How can I retrieve the name from my contact_list using phone? For example, I have the 147889, how can I retrieve Joe?

I have tried this

User.query.filter(User.contact_list.contains({"phone": ["147889"]})).all()

But, it returns me an empty list, []

How can I do this?


回答1:


You just forgot that your JSON path should include the outermost array as well:

User.query.filter(User.contact_list.contains([{"phone": ["147889"]}])).all()

will return the user you are looking for. The original query would match, if your JSON contained an object with key "phone" etc. Note that this returns the User object in question, not the specific object/name from the JSON structure. If you want that, as seems to be the end goal, you could expand the array elements of each user, filter based on the resulting records, and select the name:

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()

On the other hand the above query is not as index friendly as the first one can be, because it has to expand all the arrays before filtering, so it might be beneficial to first find the users that contain the phone in their contact list in a subquery or CTE, and then expand and filter.



来源:https://stackoverflow.com/questions/52190109/how-to-query-json-array-in-postgres-with-sqlalchemy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!