代码之家  ›  专栏  ›  技术社区  ›  user3505901

SQLAlchemy,查询嵌套的jsonb值每次返回空列表

  •  1
  • user3505901  · 技术社区  · 4 年前

    给定以下模型:

    from . import db 
    from sqlalchemy.dialects.postgresql import JSONB
    
    
    class Info(db.Model):
        id = db.Column(db.Integer, primary_key=True, unique=True, autoincrement=True)
        name = db.Column(db.String(100), nullable=False, unique=True)
        meta = db.Column(JSONB, nullable=False)
    
        def __repr__(self):
            return '<Config {}>'.format(self.name)
    

    以及以下数据:

    {
      "name": "pudding"
      "meta": {
        "available_in": {
          "cups": true
         }
      }
    }
    

    我想查询 cups 元字段旁边的字段。我看过各种各样的例子,但它对我不起作用,我的列表总是返回一个空白列表。

    query = db.session.query(Info).filter(Info.meta['available_in', 'cups'].astext=='true').all()
    
    # returns []
    

    有人知道正确的方法吗?

    1 回复  |  直到 4 年前
        1
  •  1
  •   snakecharmerb    4 年前

    根据JSON类型的文档,您需要以元组的形式提供密钥路径。

    可以使用以下命令将结果转换为布尔值 comparator.as_boolean 如果您使用的是SQLAlchemy 1.3.11或更高版本,则需要进行数据转换,否则需要按照文档中的描述进行转换。

    session.query(Info).filter(Info.meta[('available_in', 'cups')].as_boolean())
    
        2
  •  1
  •   Ruben Helsloot Rez    4 年前

    SQLAlchemy将嵌套的JSONB元素放入嵌套的Python字典中,因此您应该使用 Info.meta['available_in']['cups'] 相反。其次,演员阵容 Info.meta['available_in', 'cups'].astext 先将其转换为布尔值,然后将其与 sqlalchemy.True() 或者就这样。

    query = db.session.query(Info)\
        .filter(Info.meta['available_in']['cups'].as_boolean()).all()
    

    它返回的SQL查询是

    SELECT info.id,
           info.name,
           info.meta
    FROM info
    WHERE CAST((info.meta -> 'available_in') ->> 'cups' AS BOOLEAN)
    

    感谢@snakecharmerb指出这一点 comparator.as_boolean 现在存在。