具有一对多关系的 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 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 查询时,我可以查询扫描、结果、主机信息、端口信息、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 处理一对多的最佳方法