Циклические запросы GraphQL с отношениями один-ко-многим

Я изучаю GraphQL, создавая простое приложение на Python, которое в основном запускает 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?


person user1960118    schedule 22.04.2018    source источник


Ответы (2)


Что вам нужно сделать:


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
         }
      }
    }
}
person DPalharini    schedule 28.07.2020

Я знаю, что преобразователи для каждого поля с 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):
            .
            .
            .
person Community    schedule 24.04.2018