python - 带有 json 数组的 Postgres/SqlAlchemy 选择记录包含来自另一个 json 数组的至少 1 个 json
问题描述
我有以下架构:
CREATE TABLE rate_plan (
rate_plan_id SERIAL PRIMARY KEY,
room_type_occupancy_mappings JSONB NOT NULL
);
INSERT INTO rate_plan
VALUES
(1, '[{"adult_count": 1, "room_type_id": "RT01"}, {"adult_count": 1, "room_type_id": "RT02"}, {"adult_count": 1, "room_type_id": "RT03"}, {"adult_count": 1, "room_type_id": "RT04"}]'),
(2, '[{"adult_count": 2, "room_type_id": "RT02"}]'),
(3, '[{"adult_count": 1, "room_type_id": "RT02"}]');
现在,从这个模式中,我试图获取记录,其中room_type_occupancy_mappings
json 数组包含来自另一个 json 数组的至少一个 json。
在这种情况下,假设我有一个 json 数组:
[{"room_type_id": "RT02", "adult_count": 2"}, {"room_type_id": "RT03", "adult_count": 1"}]
我需要数组中包含一个或所有这些 json 的所有记录。这我可以用这个查询来做:
SELECT rate_plan_id, room_type_occupancy_mappings
FROM rate_plan
WHERE EXISTS (
SELECT 1
FROM jsonb_array_elements(room_type_occupancy_mappings) x
WHERE (x->>'room_type_id', (x->>'adult_count')::int) IN (('RT02', 2), ('RT03', 1)));
我面临的问题是将这个查询转换为 SQLAlchemy。我试图做这样的事情:
query = self.session().query(RatePlan).filter(
exists(
select([1]).select_from(
func.jsonb_array_elements(self._model.room_type_occupancy_mappings)
.filter(tuple_(self._model.room_type_occupancy_mappings['room_type_id'].astext,
self._model.room_type_occupancy_mappings['adult_count'].astext.cast(Integer))
).in_([(‘RT02’, 2), (‘RT03’, 1)]))))
但这会导致错误。我也试过这个查询:
query = self.session().query(RatePlan).filter(
repo.session().query(func.jsonb_array_elements(repo._model.room_type_occupancy_mappings).alias('rtom'))
.filter(tuple_(rtom['room_type_id'].astext,
rtom['adult_count'].astext.cast(Integer)
).in_([('RT02', 2), ('RT03', 1)])).exists())
但这也会导致错误。
有没有办法将此查询转换为 SqlAlchemy?或者我应该更好地将此 JSONB 类型转换为单独的表。现在,RoomTypeOccupancyMapping
是我的实体建模中的一个值对象。
解决方案
最后,我使用以下查询使其工作:
rtom_value = literal_column('rtom.value', type_=JSONB)
query = self.session().query(RatePlan).filter(
self.session().query().select_from(func.jsonb_array_elements(self._model.room_type_occupancy_mappings).alias('rtom'))
.filter(tuple_(rtom_value['room_type_id'].astext,
rtom_value['adult_count'].astext.cast(Integer)
).in_([('RT02', 2), ('RT03', 1)])).exists())
推荐阅读
- mido - MIDO:ValueError:变量 int 必须是正整数
- amazon-web-services - AWS Go 开发工具包凭证发现
- r - Bookdown:如何使脚注中的引用出现在章节引用中?
- excel - 汇总 Excel COM 对象中的多列
- html - 不能让 3 个元素彼此相邻浮动
- javascript - 无法读取 null 的属性“角色”。在加入服务器后向用户添加角色时
- groovy - 在 Groovy 中访问映射中的键时遇到问题
- python - 使用 selenium 和 python 从下拉按钮中选择选项
- javascript - Discord.js ts1381
- swift - 当测试目标从 CocoaPods 管理中排除时,为什么不构建单元测试?