Requête de filtre Postgresql SQLalchemy pour la liste des chaînes jsonb

Aug 18 2020

Veuillez m'excuser car je suis nouveau sur SQLalchemy et encore débutant avec Postgresql.

J'ai une colonne de chaîne jsonb indexée gin qui ressemble à ci-dessous:

my_id| my_column
0    | "AAAA"
1    | "BBBB"
2    | "CCCC"

Je dois rechercher dans 'my_column' 'AAAA' et 'CCCC' car je ne reçois que cette chaîne. Cela devrait être fait de préférence sans boucle for car il y a des centaines de ces chaînes. 'my_column' appartient à la table 'my_table'. La colonne 'my_id' est la clé primaire. La requête sql explicite juste pour 'AAAA' serait :

select * from my_table
where my_column ? 'AAAA'

En utilisant SQLalchemy, la requête pour cela serait en python quelque chose comme :

from sqlalchemy import create_engine, Column, Integer
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import JSONB

Base = declarative_base()

class my_class(Base):
__tablename__ = 'my_table'
my_id     =  Column(Integer, primary_key=True)
my_column =  Column(JSONB)

engine = create_engine('postgresql+psycopg2://user:pass@host/db')
session = sessionmaker(bind=engine)()

session.query(my_class).filter(my_class.my_column.has_key("AAAA").all()

Je sais qu'il est possible d'interroger une liste d'entiers en utilisant la clause in comme ci-dessous:

session.query(my_class).filter(my_class.example_id.in_((123,456))).all()

Mais je n'ai pas réussi à utiliser comme ça:

session.query(my_class).filter(my_class.my_column.in_(('AAAA','CCCC'))).all()

Existe-t-il un moyen d'interroger une liste de chaînes dans une colonne jsonb sans recourir à une boucle ? Est-il possible d'entrer simplement un paramètre de type liste contenant toutes les chaînes sans taper explicitement toutes les chaînes que je souhaite rechercher comme suit :

session.query(my_class).filter(my_class.my_column.in_(([list_full_of strings]))).all()

ÉDITER:

A partir de la requête :

session.query(my_class).filter(my_class.my_column.in_(('AAAA','CCCC'))).all()

L'erreur suivante se produit :

sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for type json
LINE 3: WHERE my_table.my_column IN ('AAAA', 'CCCC')
                                        ^
DETAIL:  Token "AAAA" is invalid.
CONTEXT:  JSON data, line 1: AAAA...

[SQL: SELECT my_table.my_id AS my_table_my_id, my_table.my_column AS my_table_my_column
FROM my_table
WHERE my_table.my_column IN (%(my_column_1)s, %(my_column_2)s)]
[parameters: {'my_column_1': 'AAAA', 'my_column_2': 'CCCC'}]
(Background on this error at: http://sqlalche.me/e/13/9h9h)

Réponses

1 snakecharmerb Aug 18 2020 at 20:28

Vous pouvez créer les has_keyexpressions requises dans un fichier or_, comme ceci :

keys = ['AAAA', 'CCCC'] 
clauses = [my_class.my_column.has_key(k) for k in keys]  
recs = session.query(my_class).filter(sqlalchemy.or_(*clauses)).all()  
print([r.my_column for r in recs])

Production:

['AAAA', 'CCCC']