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

问题描述 投票:0回答:2

我正在通过构建一个简单的 python 应用程序来学习 GraphQL,基本上运行

nmap
扫描将输出存储到数据库,并且可以通过 GraphQL API 进行查询。我似乎对 GraphQL 的工作原理有点困惑。

我有几个表是一对多关系:

user has many scans
scans have results
results have hosts
hosts have ports
hosts 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 查询时,我可以查询扫描、结果、主机信息、端口信息、操作系统信息,而无需为这些字段提供解析器。我的印象是每个字段都需要一个解析器。

此外,由于外键和关系表,我似乎能够进行循环查询(因此从

scanresults
我可以查询
scans
,从
scans
我可以查询
user
)。

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

graphql graphene-python
2个回答
0
投票

你需要做的是:


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
         }
      }
    }
}

-1
投票

我知道 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):
            .
            .
            .
© www.soinside.com 2019 - 2024. All rights reserved.