問題出在一個PostgreSQL json
列cast(Unicode)
。在Postgresql VARCHAR
的情況下,它簡單地將json
映射到底層SQLAlchemy的文本類型Unicode
。換句話說,它會生成JSON的字符串表示形式,而不是提取文本內容。如果您的輸入包含轉義的unicode代碼點,則在這種情況下它們將按原樣輸出。給定一個簡單的模型Test
用json
列數據:
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."'
它應該是顯而易見的,爲什麼用轉義Unicode字符匹配將失敗。提取文本內容的正確方式,進行反向轉義逃跑的unicode,就是用astext
,它使用PostgreSQL中->>
operator:
In [13]: session.query(Test.data['summary'].astext).scalar()
Out[13]: 'Tämä on summary.'
引述JSON的函數和操作文檔:
Note: Many of these functions and operators will convert Unicode escapes in JSON strings to the appropriate single character. This is a non-issue if the input is type jsonb, because the conversion was already done; but for json input, this may result in throwing an error, as noted in Section 8.14 .
因此,在您案例:
Message.query.\
filter(Message.content['summary'].astext.match(term))
請注意,這僅適用於json
類型,而不是jsonb
,因爲json
類型不會在輸入上轉換unicode轉義。另一方面,jsonb
converts all unicode escapes to equivalent ASCII or UTF-8 characters for storage。如果我們的Test
模型包含在第二列data2 jsonb
,具有完全相同的輸入,那麼結果將是:
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"')
不過,你應該使用astext
,如果你想文本而不是JSON的字符串表示。
你需要'cast'方法嗎?解析必須在解析JSON之前執行*,因此當您訪問content ['summary']'時,應該已經發生了。 – lenz
@lenz可能是的,否則如果我刪除它,我得到這個錯誤sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError)運算符不存在:json @@ tsquery 線3:WHERE bots_messages.content - >'summary'@ @ to_tsquery(bla bla bla – EzzatA
)你應該在問題中包括'Message'的定義,因爲它是手頭問題的關鍵部分(json vs. jsonb)。 –