skittles789
skittles789

Reputation: 135

Query a specific JSON column (postgres) with sqlalchemy

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

Answers (2)

Ilja Everilä
Ilja Everilä

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

vishes_shell
vishes_shell

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

Related Questions