具有一对多关系的 GraphQL 循环查询

Posted

技术标签:

【中文标题】具有一对多关系的 GraphQL 循环查询【英文标题】:GraphQL circular queries with one to many relationships 【发布时间】:2018-10-02 18:43:13 【问题描述】:

我正在通过构建一个简单的 python 应用程序来学习 GraphQL,基本上运行 nmap 扫描将输出存储到数据库,并且可以通过 GraphQL API 进行查询。我似乎对 GraphQL 的工作原理有点困惑。

我有几个表是一对多关系:user has many scansscans have resultsresults have hostshosts have portshosts have os。我使用sqlalchemy 定义并使用graphene

现在,在我的 GraphQL 架构中,我有:

class Scans(SQLAlchemyObjectType):
    class Meta:
        model = ScansModel


class ScanResult(SQLAlchemyObjectType):
    class Meta:
        model = ScanResultModel


class Hosts(SQLAlchemyObjectType):
    class Meta:
        model = HostInfoModel


class Ports(SQLAlchemyObjectType):
    class Meta:
        model = PortInfoModel


class Os(SQLAlchemyObjectType):
    class Meta:
        model = OsInfoModel

class Query(graphene.ObjectType):
    user = graphene.Field(User)
    scans = graphene.List(Scans)
    scan_results = graphene.List(ScanResult)
    hosts = graphene.List(Hosts)
    ports = graphene.List(Ports)
    os = graphene.Field(Os)

    def resolve_scans(self, info):
        query = Scans.get_query(info)
        return query

现在,当我进行 GraphQL 查询时,我可以查询扫描、结果、主机信息、端口信息、osinfo,而无需为这些字段使用解析器。我的印象是这些字段中的每一个都需要一个解析器。

此外,由于外键和关系表,我似乎能够进行循环查询(所以从scanresults 我可以查询scans,从scans 我可以查询user)。

这是正确的行为,还是误解了 GraphQL 的工作原理?

【问题讨论】:

【参考方案1】:

你需要做的是:


class ScanResult(SQLAlchemyObjectType):
    class Meta:
        model = ScanResultModel

    scans = graphene.List(Scans, description="Scans from results.")

    def resolve_scans(self, info):
        query = Scans.get_query(info)
        return query.filter(ScansModel.my_id == self.scans_id).all()

这可能使您能够构建如下查询:


  scanresult
    edges 
      node 
         id
         scans
            id
         
      
    

【讨论】:

【参考方案2】:

我知道每个带有 SQLAlchemyObjecType 的字段的解析器都是在库中处理的。

当我使用 mongoengine 而不使用 MongoengineObjectType 时,我的代码是这样的。

class Query(graphene.ObjectType):

    department = graphene.List(of_type=DepartmentField,
                           name=graphene.String(default_value="all"))

    role = graphene.List(of_type=RoleField,
                     name=graphene.String(default_value="all"))

    employee = graphene.List(of_type=EmployeeField,
                         name=graphene.String(default_value="all"))

    def resolve_department(self, info, name):
        if name == "all":
            department = [construct(DepartmentField, object) for object in DepartmentModel.objects]
            return department
        else:
            department = DepartmentModel.objects.get(name=name)
            return [construct(DepartmentField, department)]

    def resolve_role(self, info, name):
            .
            .
            .

【讨论】:

以上是关于具有一对多关系的 GraphQL 循环查询的主要内容,如果未能解决你的问题,请参考以下文章

具有一对多关系的灵活查询

使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法

graphql/graphcool:如何编写一个连接一对一和一对多关系的突变

jooq 具有一对多关系的单个查询

创建具有多个一对多关系的 DAO 查询?

如何使用 GraphQL 创建一对多关系?