PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Texte SQLAlchemy Correspondance des données dans le champ JSON avec UTF-8

Le problème réside dans cast(Unicode) d'un json Postgresql colonne. Il CAST simplement le json au type de texte sous-jacent à Unicode de SQLAlchemy , dans le cas de Postgresql VARCHAR . En d'autres termes, il produit une représentation sous forme de chaîne de JSON au lieu d'extraire le contenu du texte. Si votre entrée contenait des points de code Unicode échappés, ils sont sortis tels quels dans ce cas. Étant donné un simple Test modèle avec un json colonne données :

In [7]: t = Test(data={'summary': 'Tämä on summary.'})

In [8]: session.add(t)

In [9]: session.commit()

In [11]: session.query(Test.data['summary'].cast(Unicode)).scalar()
Out[11]: '"T\\u00e4m\\u00e4 on summary."'

La raison pour laquelle une correspondance avec des caractères Unicode non échappés échouera devrait être évidente. La bonne façon d'extraire le contenu du texte, sans échapper à l'unicode échappé, consiste à utiliser astext , qui utilise le ->> opérateur dans Postgresql :

In [13]: session.query(Test.data['summary'].astext).scalar()
Out[13]: 'Tämä on summary.'

Citant la documentation des fonctions et des opérateurs JSON :

Donc dans votre cas :

Message.query.\
    filter(Message.content['summary'].astext.match(term))

Notez que cela ne s'applique qu'à json tapez, pas jsonb , car le json type ne convertit pas les échappements unicode en entrée. jsonb d'autre part convertit tous les échappements unicode en équivalent ASCII ou UTF-8 caractères pour le stockage . Si notre Test le modèle contenait une deuxième colonne data2 jsonb , avec exactement la même entrée, alors le résultat serait :

In [11]: session.query(Test.data['summary'].cast(Unicode),
    ...:               Test.data2['summary'].cast(Unicode)).first()
Out[11]: ('"T\\u00e4m\\u00e4 on summary."', '"Tämä on summary"')

Néanmoins, vous devez utiliser astext , si vous voulez du texte au lieu d'une représentation sous forme de chaîne de JSON.