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

时间:2018-04-22 17:43:27

标签: graphql graphene-python

我正在通过构建一个简单的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查询时,我可以查询扫描,结果,hostinfo,portinfo,osinfo,而无需为这些字段设置解析器。我的印象是每个领域都需要一个解析器。

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

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

2 个答案:

答案 0 :(得分:0)

我知道使用SQLAlchemyObjecType的每个字段的解析器都在库内处理。

当我在不使用MongoengineObjectType的情况下使用mongoengine时,我的代码就像这样。

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):
            .
            .
            .

答案 1 :(得分: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
         }
      }
    }
}