PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

SQLAlchemy Text Corrispondenza dei dati all'interno del campo JSON con UTF-8

Il problema risiede in cast(Unicode) di un json Postgresql colonna. Trasmette semplicemente il json al tipo di testo sottostante Unicode di SQLAlchemy , nel caso di Postgresql VARCHAR . In altre parole, produce una rappresentazione di stringa di JSON invece di estrarre il contenuto del testo. Se il tuo input conteneva codepoint Unicode sfuggiti, vengono emessi come in questo caso. Dato un semplice Test modello con un json colonna dati :

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."'

Dovrebbe essere evidente il motivo per cui una corrispondenza con caratteri Unicode senza caratteri di escape fallirà. Il modo corretto per estrarre il contenuto del testo, senza escape unicode con escape, è usare astext , che utilizza ->> operatore in Postgresql:

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

Citando la documentazione delle funzioni e degli operatori JSON:

Quindi nel tuo caso:

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

Nota che questo vale solo per json digita, non jsonb , perché json type non converte gli escape Unicode in input. jsonb d'altra parte converte tutti gli escape unicode in ASCII o UTF-8 equivalenti caratteri per la memorizzazione . Se il nostro Test model conteneva una seconda colonna data2 jsonb , con lo stesso identico input, il risultato sarebbe:

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"')

Tuttavia, dovresti usare astext , se vuoi testo invece di una rappresentazione di stringa di JSON.