【问题标题】:Recursive/Nested/Tree Data fetching in hasurahasura中的递归/嵌套/树数据获取
【发布时间】:2020-10-05 07:07:11
【问题描述】:

我的用户表具有与组织单位表 (1-1) 关系的外键,即 1 个用户属于 1 个组织单位。

我有 org-unit 表,其中包含 parent-id(self-reference) 列,即 org-unit 可以嵌套。例如orgUnit_1 的父 ID 为 null,orgUnit_2 的父 ID 为 1,orgUnit_3 的父 ID 为 2。

orgUnit_1
    - orgUnit_2
        -orgUnit_3

user1 belongs to orgUnit_1
user2 belongs to orgUnit_2
user3 belongs to orgUnit_3

现在我希望,当我从 orgUnit_1 获取用户时,它也应该带来它的子 orgUnit 用户......即 user1、user2 和 user3。

这可能吗,在哈苏拉?

【问题讨论】:

    标签: postgresql graphql hasura


    【解决方案1】:

    GraphQL 不支持递归查询,但可以在 PostgreSQL 中使用递归公用表表达式。这可以定义为一个函数并用作表计算域:

    drop function if exists organization_descendant_users(organization);
    drop table if exists user_info;
    drop table if exists organization;
    
    create table organization (
        id serial primary key,
        parent int references organization(id),
        organization text not null
    );
    
    insert into organization(id, parent, organization)
    values
        (1, null, '/'),
        (2, 1, '/a'),
        (3, 2, '/a/a'),
        (4, 1, '/b'),
        (5, 4, '/b/a'),
        (6, 4, '/b/b');
    
    alter sequence organization_id_seq restart with 7;
    
    create table user_info (
        id serial primary key,
        email text unique,
        organization int not null references organization(id)
    );
    
    insert into user_info (id, email, organization)
    values
        (1, 'someone@a-a', 3),
        (2, 'someone@b-b', 6),
        (3, 'someone@a', 2),
        (4, 'someone@top', 1);
    
    alter sequence user_info_id_seq restart with 5;
    
    create function organization_descendant_users(organization_row organization)
    returns setof user_info as $$
    with recursive organization_descendant as (
        select
            id,
            id as descendant
        from organization
        union all
        select
            o.parent as id,
            n.descendant
        from organization o
        join organization_descendant n on n.id = o.id
    )
    select user_info.*
    from organization_descendant
    join user_info on user_info.organization = organization_descendant.descendant
    where organization_descendant.id is not null and organization_descendant.id = organization_row.id
    order by email;
    $$ language sql stable;
    
    create index on organization(parent);
    create index on user_info(organization);
    

    跟踪user_infoorganization 表并修改表organization 并将organization_descendant_users 作为计算字段添加到表中。

    查询示例:

    query {
      organization {
        organization
        organization_descendant_users {
          email
        }
      }
    }
    

    结果:

    {
      "data": {
        "organization": [
          {
            "organization": "/",
            "organization_descendant_users": [
              {
                "email": "someone@a"
              },
              {
                "email": "someone@a-a"
              },
              {
                "email": "someone@b-b"
              },
              {
                "email": "someone@top"
              }
            ]
          },
          {
            "organization": "/a",
            "organization_descendant_users": [
              {
                "email": "someone@a"
              },
              {
                "email": "someone@a-a"
              }
            ]
          },
          {
            "organization": "/a/a",
            "organization_descendant_users": [
              {
                "email": "someone@a-a"
              }
            ]
          },
          {
            "organization": "/b",
            "organization_descendant_users": [
              {
                "email": "someone@b-b"
              }
            ]
          },
          {
            "organization": "/b/a",
            "organization_descendant_users": []
          },
          {
            "organization": "/b/b",
            "organization_descendant_users": [
              {
                "email": "someone@b-b"
              }
            ]
          }
        ]
      }
    }
    

    【讨论】:

      【解决方案2】:

      不,这是不可能的,因为 GraphQL 不支持递归查询请求。

      https://github.com/graphql/graphql-spec/issues/91

      你能做的最好的事情是:

      org_unit {
        id
        name
        users {
          id
          display_name
        }
        child_org_unit {
          id
          name
          users {
            id
            display_name
          }
          child_org_unit {
            id
            name
            users {
              id
              display_name
            }
            child_org_unit {
              id
              name
              users {
                id
                display_name
              }
            }
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2022-12-12
        • 1970-01-01
        • 2021-11-01
        • 2023-01-11
        • 2015-08-04
        • 2019-09-21
        • 1970-01-01
        • 2011-11-10
        • 1970-01-01
        相关资源
        最近更新 更多