Using JSON Type with Flask-sqlalchemy & Postgresql
Looking at the SQLAlchemy documentation for the JSON data type it appears that you should be able to use the .cast
method:
from sqlalchemy.types import Integer
from app import app, db
from models import Target
# SQLAlchemy 1.1+
data = Target.query.order_by(Target.product['salesrank'].astext.cast(Integer))
# SQLAlchemy < 1
data = Target.query.order_by(Target.product['salesrank'].cast(Integer))
larrywgray
Living in the Code! Loving my Family! Having a Great time! Postdoctoral Fellow - Computational Biology Branch - Structure Group at National Center for Biotechnology Information Past Co-Founder at BusyGrad Inc PhD Candidate - Cellular and Molecular Physiology at Johns Hopkins School of Medicine Predoctoral Fellow - National Research Service Award - NIDDK at Johns Hopkins University, School of Medicine
Updated on July 09, 2022Comments
-
larrywgray almost 2 years
Background: I am building a Flask App and I have stored my data into a postgresql database and within a JSON column type.
Task: In my view functions, I would like to order a database query by {Key:Value} from JSON column
Accomplished: I have been successful in performing this query at the psql command-line by using the following command for example:
select * from target where cast(product->>'profit' as float) > 100 order by cast(product->>'salesrank' as integer) asc;
Problem: I can not replicate this query in my code (see code for Model below in Extra Info Section)
from app import app, db from models import Target data = Target.query.order_by(Target.product['salesrank'])
Error received - ProgrammingError: (ProgrammingError) could not identify an ordering operator for type json LINE 2: FROM target ORDER BY target.product -> 'salesrank' ^ HINT: Use an explicit ordering operator or modify the query. 'SELECT target.id AS target_id, target.store AS target_store, target.product AS target_product, target.asin AS target_asin, target.date AS target_date \nFROM target ORDER BY target.product -> %(product_1)s \n LIMIT %(param_1)s' {'product_1': 'salesrank', 'param_1': 1}
Extra Info My Target model was set up as such:
#models.py from app import db from sqlalchemy.dialects.postgresql import JSON import datetime class Target(db.Model): __tablename__ = 'target' id = db.Column(db.Integer) store = db.Column(db.String()) product = db.Column(JSON) asin = db.Column(db.String(), primary_key=True) date = db.Column(db.DateTime, default=datetime.datetime.utcnow())
My App.py file where I define Flask and Sqlalchemy
from flask import Flask import os from flask.ext.sqlalchemy import SQLAlchemy from flask_bootstrap import Bootstrap app = Flask(__name__) app.config.from_object(os.environ['APP_SETTINGS']) db = SQLAlchemy(app) Bootstrap(app) import views from app import app from models import Result if __name__ == '__main__': app.run(host='192.168.1.5', port=5000, debug=True)
Thank you for any help you can provide!
-
larrywgray almost 10 yearsI came across this in the docs, tried this several times before but only got "Integer" unknown error --- I now realized that I just needed to import INTEGER from sqlalchemy.dialects.postgresql to make it work. Correct code is:
-
larrywgray almost 10 yearsor Integer from sqlalchemy.types as you have suggested in order to make it work.
-
Ilja Everilä over 5 yearsSince version 1.1 the
JSONElement.cast()
shortcut is gone: "Changed in version 1.1: TheColumnElement.cast()
operator on JSON objects now requires that theJSON.Comparator.astext
modifier be called explicitly, if the cast works only from a textual string."