4

I can't work out how to use SQLAlchemy to query a table that contains JSONB data.

The JSON structure is similar to this:

example = {
  "product": "Widget",
  "version": 1,
  "release_date": "2019-07-01T00:00:00.000Z",
  "widget": {
    "code": "ABCDEF",
    "name": "my widget",
    "uses": {
        "rain": "yes",
        "snow": "no",
        "heat": "sometimes",
...

I'm trying to execute a query with this functionality:

SELECT
    json  AS acdata
FROM
    aircraft.aircraft
WHERE json -> 'widget' -> 'uses' ->> 'rain' = 'No';

in this form:

widget= session.query(Widget).filter_by(rain='No').first()

I know the rain='No' isn't correct but I can't work out what should go there! The objective is to get the first Widget whose key widget.uses.rain = 'No'

I have this definition for my Widget class

from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.dialects.postgresql import JSONB, UUID

class Widget(Base):
    __tablename__ = 'widgets'
    __table_args__ = {'schema' : 'factory'}

    id = Column(UUID(as_uuid=True), primary_key=True)
    json = Column(JSONB, nullable=False)
...
1

1 Answer 1

2

To access a nested jsonb value use a tuple of keys (path index operation) and astext to convert the value as text:

widget = session.query(Widget).\
    filter(Widget.json["widget", "uses", "rain"].astext == 'No').\
    first()

The resulting query uses the #>> operator for the path index + astext operation. You cannot use filter_by() for this kind of predicate, as it is used for simple equality checks against attributes of a model class.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that was exactly what i was looking for!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.