sql >> Base de Datos >  >> RDS >> PostgreSQL

Datos de coincidencia de texto de SQLAlchemy dentro del campo JSON con UTF-8

El problema radica en cast(Unicode) de un Postgresql json columna. Simplemente lanza el json al tipo de texto subyacente a Unicode de SQLAlchemy , en el caso de Postgresql VARCHAR . En otras palabras, produce una representación de cadena de JSON en lugar de extraer el contenido del texto. Si su entrada contenía puntos de código Unicode escapados, se muestran como en este caso. Dada una simple Test modelo con un json columna datos :

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

Debería ser evidente por qué fallará una coincidencia con caracteres Unicode sin escape. La forma correcta de extraer el contenido del texto, sin escape de unicode escapado, es usar astext , que utiliza el ->> operador en PostgreSQL:

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

Citando la documentación de operadores y funciones JSON:

Así que en tu caso:

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

Tenga en cuenta que esto solo se aplica a json tipo, no jsonb , porque el json type no convierte los escapes Unicode en la entrada. jsonb por otro lado, convierte todos los escapes Unicode a ASCII o UTF-8 equivalentes caracteres para almacenamiento . Si nuestra Test el modelo contenía una segunda columna data2 jsonb , con exactamente la misma entrada, entonces el resultado sería:

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

Aún así, deberías usar astext , si desea texto en lugar de una representación de cadena de JSON.