Skip to content

Instantly share code, notes, and snippets.

@fenos
Last active June 26, 2019 10:15
Show Gist options
  • Save fenos/fc4672d32f179b27aec8b92a819ee8ba to your computer and use it in GitHub Desktop.
Save fenos/fc4672d32f179b27aec8b92a819ee8ba to your computer and use it in GitHub Desktop.
Dataloader and GraphQL passing arguments
// GraphQL query that i'm trying to resolve with Dataloader but i can't find a way to pass argument to the
// loader function.
// The following GraphQL query should invoke the following DB round trips
// 1 - Posts *
// 2 - Tags limit 10 where post_id = ?
// 3 - Tags limit 20 where post_id = ?
query limitTagsOfThePost {
posts {
name
tags(limit: 10) {
name
}
tags(limit: 20) {
name
}
}
}
// GraphQL Types: Tag and Posts
const TagType = new GraphQLObjectType({
name: 'Tag',
fields: () => {
return {
id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: new GraphQLNonNull(GraphQLString)
}
};
}
});
const PostType = new GraphQLObjectType({
name: 'Post',
fields: () => {
return {
id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: GraphQLString
},
tags: {
type: new GraphQLList(TagType),
resolve: (post, {limit}) => {
// Here I have the LIMIT argument which allows me
// to limit the tags of the posts. But i can't understand
// which pattern i should use to allow the argument to be injected
// into the getPostTagsUsingPostId loader function.
return TagByPostIdLoader.load(post.id);
}
}
};
}
});
const TagByPostIdLoader = new DataLoader(getPostTagsUsingPostId);
// Loader
// Here i want to have the args passed from the GraphQL query
// maybe as a second argument? so that i can add limit to the tags.
const getPostTagsUsingPostId = (postIds) => {
return Post
.collection(postIds.map((id) => {
return {
id
};
}))
.load('tags')
.call('toJSON')
.then((collection) => {
// Bookshelf 0.10.0 uses Bluebird ^2.9.4.
// Support for .mapSeries has been added in Bluebird v3.
return collection.map((post) => {
return post.tags;
});
});
};
@kamek-pf
Copy link

Did you ever find a solution @fenos ?
I'm facing a similar problem, I can't really find anything.

@DaveyEdwards
Copy link

I am also having this issue, anyone find a solution?

@0xMillz
Copy link

0xMillz commented Aug 10, 2018

Me too. Anyone?

@rmoura-92
Copy link

for someone who still needs something look alike to achieve this:

import cloneDeep from 'lodash/cloneDeep';
import isObjectLike from 'lodash/isObjectLike';

const options = {
  cacheKeyFn: (key) => (isObjectLike(key)) ? JSON.stringify(cloneDeep(key)) : key,
};

const mergeKeys = arr => ({
  keys: _.map(arr, 'key'),
  args: _.merge(...(_.map(arr, 'arguments')))
});

const loader = async (data, { User }) => { // User is the model
  const { keys, args } = mergeKeys(data);

  const pagination = args.pagination ? args.pagination : {};

  console.log(pagination)
  const users = await User.findAll({
    raw: true,
    where: {
      id: {
        $in: keys,
      }
    },
    ...pagination,
  });

  console.log(users);

  const groupUsers = _.groupBy(users, 'id');
  return keys.map(key => groupUsers[key]);
  
}

new DataLoader((keys) => loader(keys, models), options)

@BartusZak
Copy link

Not working for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment