jkimbo / graphql-sync-dataloaders

Use DataLoaders in your Python GraphQL servers that have to run in a sync context (i.e. Django).
MIT License
41 stars 21 forks source link

How to check that this is actually working? #13

Open mahdyhamad opened 1 year ago

mahdyhamad commented 1 year ago

Hello : ) I am getting my feet wet in Data Loaders by asking some questions and I might be doing something wrong here. I would appreciate the help!

I am trying to use this implementation to solve the n+1 problem, in parallel with validating if the SQL queries are less or the same after using this implementation of DataLoader.

I have fetched the same query multiple times in one operation (following the example in the readme) To validate if query is optimized, I use the debug query to make sure sql queries are actually less.

Here is an example of the query:

{
  query1: user(id:"VXNlck5vZGU6MQ=="){
    id
  }

  query2: user(id:"VXNlck5vZGU6Mg=="){
    id
  }

  query3: user(id:"VXNlck5vZGU6Mw=="){
    id
  }

  _debug { 
    sql{
      alias
      rawSql
    }
  }
}

I get 3×m SQL Queries where m is the number of sql queries per campaign Graphql-query. The number of SQL queries is the same without using data loading

dataloaders.py

from graphql_sync_dataloaders import SyncDataLoader

def load_userss(keys):
    users = User.objects.all().in_bulk(keys)
    return [users.get(key) for key in keys]

user_loader = SyncDataLoader(load_users)

schema.py

class Query:
    user = graphene.Field(UserNode, id=graphene.ID(required=True))

    @requires_role(["admin"])
    def resolve(self, info, id):
        node_type, local_id = graphql_relay.from_global_id(campaign_id)
        user = User.objects.get(id=local_id)
        return user_loader.load(user.id)

requirements

Django==3.2.16
django-graphene==3.0.0

graphql-relay==3.2.0
graphene-federation==3.0.3
gql==3.4.0

I am missing anything?

pfcodes commented 10 months ago

Hello : ) I am getting my feet wet in Data Loaders by asking some questions and I might be doing something wrong here. I would appreciate the help!

I am trying to use this implementation to solve the n+1 problem, in parallel with validating if the SQL queries are less or the same after using this implementation of DataLoader.

I have fetched the same query multiple times in one operation (following the example in the readme) To validate if query is optimized, I use the debug query to make sure sql queries are actually less.

Here is an example of the query:

{
  query1: user(id:"VXNlck5vZGU6MQ=="){
    id
  }

  query2: user(id:"VXNlck5vZGU6Mg=="){
    id
  }

  query3: user(id:"VXNlck5vZGU6Mw=="){
    id
  }

  _debug { 
    sql{
      alias
      rawSql
    }
  }
}

I get 3×m SQL Queries where m is the number of sql queries per campaign Graphql-query. The number of SQL queries is the same without using data loading

dataloaders.py

from graphql_sync_dataloaders import SyncDataLoader

def load_userss(keys):
    users = User.objects.all().in_bulk(keys)
    return [users.get(key) for key in keys]

user_loader = SyncDataLoader(load_users)

schema.py

class Query:
    user = graphene.Field(UserNode, id=graphene.ID(required=True))

    @requires_role(["admin"])
    def resolve(self, info, id):
        node_type, local_id = graphql_relay.from_global_id(campaign_id)
        user = User.objects.get(id=local_id)
        return user_loader.load(user.id)

requirements

Django==3.2.16
django-graphene==3.0.0

graphql-relay==3.2.0
graphene-federation==3.0.3
gql==3.4.0

I am missing anything?

If I understand how this library works correctly you should be doing

user = user_loader.load(user.id)