jsonb查询与数组中的嵌套对象

Tim*_*imo 9 sql postgresql relational-division jsonb postgresql-9.4

我正在使用PostgreSQL 9.4,其中teams包含一个jsonb名为的列的表json.我正在寻找一个查询,我可以让所有拥有球员的球队3,4以及7他们的球员阵容.

该表包含两行,包含以下json数据:

第一排:

{
    "id": 1,
    "name": "foobar",
    "members": {
        "coach": {
            "id": 1,
            "name": "A dude"
        },
        "players": [
            {
                "id": 2,
                "name": "B dude"
            },
            {
                "id": 3,
                "name": "C dude"
            },
            {
                "id": 4,
                "name": "D dude"
            },
            {
                "id": 6,
                "name": "F dude"
            },
            {
                "id": 7,
                "name": "G dude"
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

第二排:

{
    "id": 2,
    "name": "bazbar",
    "members": {
        "coach": {
            "id": 11,
            "name": "A dude"
        },
        "players": [
            {
                "id": 3,
                "name": "C dude"
            },
            {
                "id": 5,
                "name": "E dude"
            },
            {
                "id": 6,
                "name": "F dude"
            },
            {
                "id": 7,
                "name": "G dude"
            },
            {
                "id": 8,
                "name": "H dude"
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

如何获得所需的团队列表?我已经尝试过一个查询,我会从成员玩家创建一个数组jsonb_array_elements(json -> 'members' -> 'players')->'id'并对它们进行比较,但我所能完成的只是一个结果,其中任何一个比较的玩家ID在一个团队中可用,而不是全部.

Erw*_*ter 13

你一次面临两个非平凡的任务.我很好奇.

  • 处理jsonb用复杂的嵌套结构.
  • 在文档类型上运行等效的关系除法查询.

首先,注册一个行类型jsonb_populate_recordset().您可以使用永久创建类型CREATE TYPE,也可以创建临时表以供临时使用(在会话结束时自动删除):

CREATE TEMP TABLE foo(id int);  -- just "id", we don't need "name"
Run Code Online (Sandbox Code Playgroud)

我们只需要id,所以不要包括name.每个文件:

将不会在输出中省略未出现在目标行类型中的JSON字段

询问

SELECT t.json->>'id' AS team_id, p.players
FROM   teams t
     , LATERAL (SELECT ARRAY (
         SELECT * FROM jsonb_populate_recordset(null::foo, t.json#>'{members,players}')
         )
       ) AS p(players)
WHERE p.players @> '{3,4,7}';
Run Code Online (Sandbox Code Playgroud)

SQL捣鼓json在Postgres的9.3(第9.4尚未公布).

说明

瞧.

如果你在一个大表上经常运行这个查询,你可以创建一个假的IMMUTABLE函数,像上面一样提取数组,并根据这个函数创建函数GIN索引,使这个超级快.
"假"因为函数依赖于基础行类型,即在目录查找上,并且如果更改则会更改.(所以要确保它不会改变.)与此类似:

另外:
不要使用像json列名这样的类型名称(即使这是允许的),这会引发棘手的语法错误和混淆错误消息.