PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Dados de correspondência de texto SQLAlchemy dentro do campo JSON com UTF-8


O problema está em cast(Unicode) de um json Postgresql coluna. Ele simplesmente faz o CAST do json para o tipo de texto subjacente ao Unicode do SQLAlchemy , no caso do Postgresql VARCHAR . Em outras palavras, ele produz uma representação de string de JSON em vez de extrair o conteúdo do texto. Se sua entrada contiver pontos de código unicode com escape, eles serão emitidos como estão neste caso. Dado um simples Test modelo com um json coluna dados :
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."'

Deve ser evidente por que uma correspondência com caracteres unicode sem escape falhará. A maneira correta de extrair o conteúdo do texto, sem escapar do unicode com escape, é usar astext , que usa o ->> operador no Postgresql:
In [13]: session.query(Test.data['summary'].astext).scalar()
Out[13]: 'Tämä on summary.'

Citando a documentação de funções e operadores JSON:

Então no seu caso:
Message.query.\
    filter(Message.content['summary'].astext.match(term))

Observe que isso se aplica apenas a json tipo, não jsonb , porque o json type não converte escapes unicode na entrada. jsonb por outro lado, converte todos os escapes unicode em ASCII ou UTF-8 equivalentes caracteres para armazenamento . Se nosso Test modelo continha uma segunda coluna data2 jsonb , com exatamente a mesma entrada, o resultado seria:
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"')

Ainda assim, você deve usar astext , se você quiser texto em vez de uma representação de string de JSON.