python - SQLAlchemy has_any()
问题描述
我无法让 SQLAlchemy 的has_any()
功能正常工作。我只是想在 jsonb 列中包含的列表中过滤我的结果:
db.session.query(models.Record.id).\
filter(models.Record.record_metadata["teams"].has_any(team_ids))
models.Record.record_metadata["teams"]
record_metadata
作为我想要与之比较的 jsonb 列 ( )team_ids
中的 id 列表,这也是 id 列表
生成的查询是:
SELECT record.id AS record_id
FROM record
WHERE ((record.record_metadata -> 'teams')) ?| '["id1", "id2"]';
这给出了错误
DataError: (psycopg2.DataError) malformed array literal: "["id1", "id2"]"
LINE 3: WHERE ((record.record_metadata -> 'teams')) ?| '["id1", "id2"]'
^
DETAIL: "[" must introduce explicitly-specified array dimensions.
但是关于表 9.44。Postgres 官方文档上的附加 jsonb 运算符|?
,运算符后面应该跟一个array[]
事实上,当我手动编写查询时:
SELECT record.id AS record_id
FROM record
WHERE ((record.record_metadata -> 'teams')) ?| array['id1', 'id2'];
它工作得很好。
SQLAlchemy关于这个函数的文档很差,我找不到任何例子。
那么是我在这个功能上做错了吗?我应该在这种情况下使用其他东西吗?还是它has_any()
坏了?
编辑 :
SELECT record.id AS record_id
FROM record
WHERE ((record.record_metadata -> 'teams')) ?| '{"id1", "id2"}';
工作得很好,我发现它也has_any()
接受字符串。
所以它是一个(非常)讨厌的修复,但是如果我用所需的 id 格式化一个字符串:
db.session.query(models.Record.id).\
filter(models.Record.record_metadata["teams"].has_any(
str(team_ids).
replace('[', '{').
replace(']', '}').
replace('\'', '\"')))
有用...
解决方案
似乎默认情况下传递的值是 JSON 编码的,如果它是 alist
或 a dict
。您可以通过传递显式array
文字来解决此问题:
In [15]: from sqlalchemy.dialects.postgresql import array
In [16]: session.query(Foo).\
...: filter(Foo.data['test'].has_any(array(['1', '2']))).all()
2018-06-18 09:07:20,780 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2018-06-18 09:07:20,780 INFO sqlalchemy.engine.base.Engine SELECT foo.id AS foo_id, foo.data AS foo_data
FROM foo
WHERE ((foo.data -> %(data_1)s)) ?| ARRAY[%(param_1)s, %(param_2)s]
2018-06-18 09:07:20,781 INFO sqlalchemy.engine.base.Engine {'data_1': 'test', 'param_1': '1', 'param_2': '2'}
Out[16]: []
这样您就不需要从 Python 的字符串表示中手动格式化数组文字list
,这可能很容易出错。
错误本身是 Postgresql 试图将传递的文字(包含 JSON)解析为数组的结果。如错误所示,数组的文本表示可能以指定数组下标范围的维度装饰开始:
'[1:1][-2:-1][3:5]={{{1,2,3},{4,5,6}}}'::int[]
推荐阅读
- java - java.lang.NoClassDefFoundError: org/springframework/beans/factory/BeanNameAware
- facebook - 如何启用接收来自不在开发者列表中的人(公众)的 Facebook Bot 传入消息?
- python - 使用opencv python预测图像中的矩形
- algorithm - 对大致有序的流进行排序的最佳方法是什么?
- python - 不同人的平均访问间隔
- .net - 为什么新的 Blazor WASM 版本仅支持 .Net 5?.NET 标准呢?
- google-chrome-extension - chrome扩展实时通知
- java - LocalThread 持有 RequestScoped CDI 实例
- reactjs - 编辑文本框后重新加载反应表值
- java - 如何限制字符串生成器的长度