我正在尝试使用row_to_json()
PostgreSQL 9.2中添加的功能将查询结果映射到JSON 。
我在找出将连接的行表示为嵌套对象(1:1关系)的最佳方式时遇到麻烦
这是我尝试过的内容(设置代码:表格,示例数据,后跟查询):
-- some test tables to start out with:
create table role_duties (
id serial primary key,
name varchar
);
create table user_roles (
id serial primary key,
name varchar,
description varchar,
duty_id int, foreign key (duty_id) references role_duties(id)
);
create table users (
id serial primary key,
name varchar,
email varchar,
user_role_id int, foreign key (user_role_id) references user_roles(id)
);
DO $$
DECLARE duty_id int;
DECLARE role_id int;
begin
insert into role_duties (name) values ('Script Execution') returning id into duty_id;
insert into user_roles (name, description, duty_id) values ('admin', 'Administrative duties in the system', duty_id) returning id into role_id;
insert into users (name, email, user_role_id) values ('Dan', 'someemail@gmail.com', role_id);
END$$;
查询本身:
select row_to_json(row)
from (
select u.*, ROW(ur.*::user_roles, ROW(d.*::role_duties)) as user_role
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id
) row;
我发现如果使用ROW()
,我可以将结果字段分离为一个子对象,但似乎仅限于一个级别。我不能插入更多的AS XXX
语句,因为我认为在这种情况下我需要。
为我提供了列名,因为::user_roles
在该表的结果中,我强制转换为适当的记录类型,例如使用。
该查询返回的内容如下:
{
"id":1,
"name":"Dan",
"email":"someemail@gmail.com",
"user_role_id":1,
"user_role":{
"f1":{
"id":1,
"name":"admin",
"description":"Administrative duties in the system",
"duty_id":1
},
"f2":{
"f1":{
"id":1,
"name":"Script Execution"
}
}
}
}
我想要做的是以一种添加联接的方式为联接生成JSON(再次使用1:1即可),并将联接表示为它们联接的父级的子对象,例如:
{
"id":1,
"name":"Dan",
"email":"someemail@gmail.com",
"user_role_id":1,
"user_role":{
"id":1,
"name":"admin",
"description":"Administrative duties in the system",
"duty_id":1
"duty":{
"id":1,
"name":"Script Execution"
}
}
}
}
任何帮助表示赞赏。谢谢阅读。
更新:在PostgreSQL
9.4这提高了很多引进的to_json
,json_build_object
,json_object
和json_build_array
,虽然它冗长,由于需要明确命名所有字段:
select
json_build_object(
'id', u.id,
'name', u.name,
'email', u.email,
'user_role_id', u.user_role_id,
'user_role', json_build_object(
'id', ur.id,
'name', ur.name,
'description', ur.description,
'duty_id', ur.duty_id,
'duty', json_build_object(
'id', d.id,
'name', d.name
)
)
)
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id;
对于旧版本,请继续阅读。
它不限于单行,只是有点痛苦。您不能使用来别名复合行类型AS
,因此您需要使用别名子查询表达式或CTE来达到以下效果:
select row_to_json(row)
from (
select u.*, urd AS user_role
from users u
inner join (
select ur.*, d
from user_roles ur
inner join role_duties d on d.id = ur.duty_id
) urd(id,name,description,duty_id,duty) on urd.id = u.user_role_id
) row;
通过http://jsonprettyprint.com/产生:
{
"id": 1,
"name": "Dan",
"email": "someemail@gmail.com",
"user_role_id": 1,
"user_role": {
"id": 1,
"name": "admin",
"description": "Administrative duties in the system",
"duty_id": 1,
"duty": {
"id": 1,
"name": "Script Execution"
}
}
}
array_to_json(array_agg(...))
一对一的关系,您将要使用,顺便说一句。
理想情况下,上面的查询应该可以编写为:
select row_to_json(
ROW(u.*, ROW(ur.*, d AS duty) AS user_role)
)
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id;
…但是PostgreSQL的ROW
构造函数不接受AS
列别名。可悲的是。
值得庆幸的是,他们对它们进行了优化。比较计划:
ROW
构造函数版本已删除别名,因此可以执行由于CTE是优化屏障,因此将嵌套子查询版本改写为使用链接的CTE(WITH
表达式)可能效果不佳,并且不会得出相同的计划。在这种情况下,您会一直受困于丑陋的嵌套子查询,直到我们得到一些改进row_to_json
或ROW
更直接地覆盖构造函数中的列名的方法为止。
总之,总的来说,该原则是,您想在其中创建一个带有column的json对象a, b, c
,并且希望您可以编写非法语法:
ROW(a, b, c) AS outername(name1, name2, name3)
您可以改用标量子查询返回行类型值:
(SELECT x FROM (SELECT a AS name1, b AS name2, c AS name3) x) AS outername
要么:
(SELECT x FROM (SELECT a, b, c) AS x(name1, name2, name3)) AS outername
另外,请记住,您可以在json
不附加引号的情况下编写值,例如,如果将a的输出放在json_agg
内row_to_json
,则内部json_agg
结果不会被引用为字符串,它将直接合并为json。
例如在任意示例中:
SELECT row_to_json(
(SELECT x FROM (SELECT
1 AS k1,
2 AS k2,
(SELECT json_agg( (SELECT x FROM (SELECT 1 AS a, 2 AS b) x) )
FROM generate_series(1,2) ) AS k3
) x),
true
);
输出为:
{"k1":1,
"k2":2,
"k3":[{"a":1,"b":2},
{"a":1,"b":2}]}
请注意,json_agg
产品[{"a":1,"b":2}, {"a":1,"b":2}]
不会再次转义,就像text
那样。
这意味着您可以 组成 json操作来构造行,而不必总是创建非常复杂的PostgreSQL复合类型然后调用row_to_json
输出。
问题内容: 这是我在elasticsearch中存储在索引上的数据类型。我必须找到包含主要成分牛肉(且重量小于1000)和成分-(辣椒粉且重量小于250),(橄榄油和重量小于300)以及所有其他成分类似的食谱。 索引的映射是 我的查询是 但这给了Null。有人可以帮我吗?我认为我没有正确使用嵌套查询 问题答案: 试试这个:
问题内容: 我目前正在研究应用程序的聊天功能。并且我在StreamBuilder中设置了AnimatedList,以使消息反向显示。这是我的代码 我的问题是该构建器从未被点击,因此AnimatedList从未被调用。我不确定设置是否正确,因此对此表示感谢。 编辑:我正在尝试使其像FirebaseAnimatedList小部件一样工作。我不知道这是否有助于了解我的目标。 谢谢 问题答案: 更新:我通
根据谷歌的文档: 现在可以在片段中嵌入片段。这对于各种情况都很有用,在这些情况下,您需要将动态和可重用的UI组件放置到本身是动态和可重用的UI组件中。例如,如果使用ViewPager创建左右滑动并占用大部分屏幕空间的片段,现在可以将片段插入每个片段页面。要嵌套片段,只需对要添加片段的片段调用getChildFragmentManager()。这将返回一个FragmentManager,您可以像通常
我正在研究如何将自定义构造与SnakeYAML一起使用,但不确定如何实现嵌套。我用这个例子作为参考。 在链接的示例中,相关的YAML和构造是, 现在,让我们将YAML更改为, 我想使用另一个来解析对象,但要在上下文中进行。我对关系的理解非常不稳定,我对如何在自定义构造函数中使用自定义构造函数感到困惑。有什么想法或资源吗?
我正在尝试用多个过滤器获取帖子,我的数据库如下所示, 我尝试了上面的SQL,它可以工作,但问题是,如果我嵌套了两个以上的或条件和不同数量的过滤器,我会得到错误的结果。
问题内容: 我有一个对象A的列表。此列表中的每个对象A都包含对象B的列表,而对象B包含对象C的列表。对象C包含一个属性名称,我想使用它使用Java 8进行过滤。 如何使用流在Java 8中编写以下代码以避免嵌套循环: 问题答案: 您可以使用两个,然后使用a,然后可以选择第一个,或者如果没有结果返回: