Reputation: 135
I have a model with a JSON field:
class Item(db.Model)
...
data = db.Column(JSON, nullable=False)
...
The data contains some JSON such as:
{
"cost": 10.00,
"passengers": 2,
"surcharge": 1.6
}
I want to be able to get a sum of the cost across all rows in the table with a filter. I tried the following but that didn't seem to work.
db.session.query(func.count(Item.data['cost'])).filter(
Item.data["surcharge"].cast(Float) > 1
).scalar()
Upvotes: 5
Views: 5259
Reputation: 52939
You're using the wrong aggregate. count(expression)
counts the number of rows for which the expression is not null. If you want a sum, use sum(expression)
:
db.session.query(func.sum(Item.data['cost'].astext.cast(Numeric))).\
filter(Item.data['surcharge'].astext.cast(Numeric) > 1).\
scalar()
Note that monetary values and binary floating point math is a bad mixture due to binary floats not being able to represent all decimal values. Instead use a proper monetary type, or Numeric
in which case SQLAlchemy uses Decimal
to represent the results in Python.
Upvotes: 10
Reputation: 23484
You need to use Float
instead of Integer
as argument of cast
db.session.query(func.count(Item)).filter(
Item.data['surcharge'].cast(Float) > 1
).all()
Upvotes: 0