Python sqlalchemy按json字段筛选
我有一个带有Python sqlalchemy按json字段筛选,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,我有一个带有json列的模型。模型和数据示例: app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://...' db = SQLAlchemy() db.init_app(app) app.app_context().push() class Example(db.Model): id = db.Column(db.Integer(), nullable=False, primary_key
json列的模型。模型和数据示例:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://...'
db = SQLAlchemy()
db.init_app(app)
app.app_context().push()
class Example(db.Model):
id = db.Column(db.Integer(), nullable=False, primary_key=True, )
json_field = db.Column(db.JSON())
db.create_all()
db.session.add(Example(json_field={'id': None}))
db.session.add(Example(json_field={'id': 1}))
db.session.add(Example(json_field={'id': 50}))
db.session.add(Example(json_field={}))
db.session.commit()
现在我尝试查找id==1
的记录:
query = db.session.query(Example).filter(Example.json_field['id'] == 1)
print(query.all())
我得到了下一个错误:
sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)运算符
不存在:json=整数第3行:其中(example.json_字段->
“id')=1
原因。查看生成的查询:
SELECT example.id AS example_id, example.json_field AS example_json_field
FROM example
WHERE (example.json_field -> %(json_field_1)s) = %(param_1)s
但在我的情况下,正确的查询应该是这样的:
SELECT * FROM example WHERE CAST(json_field->>'id' AS INTEGER) = 1;
我该怎么做?
我尝试过使用,但没有成功:
print(
db.session.query(Example).filter(
cast(Example.json_field['id'], Integer) == 1
).all()
)
错误:
sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)无法
将json类型转换为整数第3行:其中转换((example.json_字段->
“id”)作为整数)=1
如您所见,where子句
仍然错误。我还需要使用range(
,Flask SQLAlchemy的SQLAlchemy
对象-通常称为db
-到SQLAlchemy
和SQLAlchemy.orm
中的函数等,因此db.JSON
是不提供Postgresql特定运算符的对象。您应该改用:
使用正确的类型后,必须显式地将第一个类型转换为整数,然后将其强制转换为整数:
db.session.query(Example).\
filter(Example.json_field['id'].astext.cast(Integer) == 1)
这将生成所需的谓词
CAST(json_field->>'id' AS INTEGER) = 1
这同样适用于不能从json
直接强制转换的所有类型。SQLAlchemy用于为astext
和cast()
的组合提供快捷方式,但在版本1.1及更高版本中已将其删除:
在版本1.1中更改:JSON
对象上的ColumnElement.cast()
运算符现在要求显式调用JSON.Comparator.astext
修饰符,如果强制转换仅从文本字符串起作用
如果您只使用过滤器(json_obj[“key”]…)
它将转换为类似sql的格式
model\u name.json\u obj->“key”
,它仍然是一个json对象
如果使用过滤器(json_obj[“key”].astext…
,则sql将
model\u name.json\u obj->“key”
,结果是一个字符串对象。您也可以在过滤器中使用原始sql
from sqlalchemy import text
db.session.query(Example).filter(text("CAST(json_field->>'id' AS INTEGER) = 1")
from sqlalchemy import text
db.session.query(Example).filter(text("CAST(json_field->>'id' AS INTEGER) = 1")