Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to query on a JSON-type field with SQLAlchemy?

This is just a simple example.

field = [[1,12,6], [2,12,8]]

I think about storing this in a json-typed field with SQLAlchemy in sqlite3 database.

But how can I query on this with SQLAlchemy (not SQL)? e.g.

  • rows where len(field) is 3
  • rows where field[1][2] is not 12
  • rows where len(field[*]) is not 3
  • group by field[2]
  • sum field[1] where field[0] is 1

Is it even possible?

Maybe it would be easier to implent this with a classical many-to-many table (incl. a link-table) instead of json-field?

like image 693
buhtz Avatar asked Aug 04 '15 08:08

buhtz


People also ask

How does the querying work with SQLAlchemy?

All SELECT statements generated by SQLAlchemy ORM are constructed by Query object. It provides a generative interface, hence successive calls return a new Query object, a copy of the former with additional criteria and options associated with it.

How do I SELECT a row in SQLAlchemy?

For both Core and ORM, the select() function generates a Select construct which is used for all SELECT queries. Passed to methods like Connection. execute() in Core and Session. execute() in ORM, a SELECT statement is emitted in the current transaction and the result rows available via the returned Result object.

What is _sa_instance_state in SQLAlchemy?

_sa_instance_state is a non-database-persisted value used by SQLAlchemy internally (it refers to the InstanceState for the instance.

What does First () do in SQLAlchemy?

first() applies a limit of one within the generated SQL, so that only one primary entity row is generated on the server side (note this may consist of multiple result rows if join-loaded collections are present). Calling Query. first() results in an execution of the underlying query.


1 Answers

According to the official documentation, these are the available methods SQLAlchemy provides for JSON Fields.

JSON provides several operations:

Index operations:

data_table.c.data['some key']

Index operations returning text (required for text comparison):

data_table.c.data['some key'].astext == 'some value'

Index operations with a built-in CAST call:

data_table.c.data['some key'].cast(Integer) == 5

Path index operations:

data_table.c.data[('key_1', 'key_2', ..., 'key_n')]

Path index operations returning text (required for text comparison):

data_table.c.data[('key_1', 'key_2', ..., 'key_n')].astext == \
'some value'

http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#sqlalchemy.dialects.postgresql.JSON

From what I know about the JSON type in PostgreSQL, it's best used only if you would want the whole JSON object. If you want to make SQL like operations on fields of the JSON object, then it's best to use classic SQL relations. Here's one source I found saying the same thing, but there are many more. http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary-jsonhstore-dynamic-columns/

like image 119
ApolloFortyNine Avatar answered Oct 19 '22 20:10

ApolloFortyNine