14

So I've got a model like such:

class myModel(Base):

    id = Column(Integer, primary_key=True)
    border = Column(JSONB)

How can I query for rows that don't have a border? I've tried:

filter(myModel.border != None) #nope
filter(myModel.border != 'null') #nope
from sqlalchemy import null
filter(myModel.border != null()) #nope

The value is apparently stored in postgres as a "JSON encoded null value". Its definitely getting serialized back to a python None when instantiated, but I have no idea how to query against it. It looks like you can set none_as_null on the column, i.e.:

Column(JSONB(none_as_null=True))

Which replaces the JSON encoded null with a SQL null, but that seems strange to have to do on all columns. What am I missing here?

edit: should mention this is v0.9.8 of sqlalchemy

6 Answers 6

5

This works for both border as JSON null and PostgresQL NULL:

from sqlalchemy.sql.expression import text
filter(myModel.border != text("'null'"))

(tested with SQLAlchemy==1.1.14)

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

1 Comment

Doesn't work for me with PostgreSQL 9.6 and SQLAlchemy 1.1.x or 1.2.x. It's throwing this error ProgrammingError: operator does not exist: json <> unknown HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. I had success importing null from sqlalchemy and comparing with null()
4

from sqlalchemy>=0.7.9, you could use the filter operator .isnot instead of comparing constraints like this - filter(myModel.border.isnot(None))

To get models with border nulls, do filter(myModel.border.is_(None))

1 Comment

This one only works when the model specifies JSONB(none_as_null=True) or JSON(none_as_null=True). See JSON.none_as_null
3

PostgreSQL has function jsonb_typeof, that returns string type of json value. So you can filter null values as jsonb_typeof(myModel.border) != 'null'. You can find details in the PostgreSQL documentation

Comments

1

Use JSON.NULL. From the docs:

To insert or select against a value that is SQL NULL, use the constant null():

from sqlalchemy import null
conn.execute(table.insert(), json_value=null())

To insert or select against a value that is JSON "null", use the constant JSON.NULL:

conn.execute(table.insert(), json_value=JSON.NULL)

So in your case,

from sqlalchemy import JSON

myModel.query.filter(myModel.border != JSON.NULL)

Comments

-1
from sqlalchemy import null

#If you try to insert data in db:  
YourModel(my_json_column = null())

#get data by filter: 
select(Table).where(Table.my_json_column.is_(None))

Comments

-2

you will be able to persist this using the value null()

>>> from sqlalchemy import null

>>> filter(myModel.border != null()) 

1 Comment

It works for me with SQLAlchemy 1.1 or 1.2 and PostgreSQL 9.6 using the type sqlalchemy.dialects.postgresql.JSON While it doesn't work the suggestion of using the comparison with text("'null'").

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.