Skip to content

Instantly share code, notes, and snippets.

@du5rte
Last active May 31, 2017
Embed
What would you like to do?
GraphQL UserConnection with totalCount
import { GraphQLInt, GraphQLNonNull, GraphQLInputObjectType } from "graphql";
import { connectionDefinitions, connectionArgs } from "graphql-relay";
import UserType from "./UserType";
// References
// http://graphql.org/learn/pagination/
// http://dev.apollodata.com/react/pagination.html
// https://www.reindex.io/blog/relay-graphql-pagination-with-mongodb/
// https://github.com/graphql/graphql-relay-js
// https://dev-blog.apollodata.com/understanding-pagination-rest-graphql-and-relay-b10f835549e7
// totalCount
// neither graphql-relay-js or relay-mongodb-connection expose totalCount
// https://github.com/mikberg/relay-mongodb-connection
// adriexnet has submitted a pull request to graphql-relay-js but the library seems a little dead
// https://github.com/adriexnet/relay-mongodb-connection/blob/develop/src/connectionFromMongoCursor.js
// graphql-relay-js can be manually overwritten throught the connectionFields
// https://stackoverflow.com/questions/34192507/how-to-pass-total-count-to-the-client-in-pageinfo
// pageInfo
// pageInfo.hasPreviousPage is always false if you are paging forwards
// https://github.com/graphql/graphql-relay-js/issues/58
// https://github.com/graphql/graphql-relay-js/issues/103
// relay-mongodb-connection uses it's own logic which can be modified here
// https://github.com/adriexnet/relay-mongodb-connection/blob/develop/src/utils.js#L39
export const {
connectionType,
edgeType
} = connectionDefinitions({
nodeType: UserType,
connectionFields: () => ({
totalCount: {
type: new GraphQLNonNull(GraphQLInt),
resolve: connection => connection.totalCount,
// description: `A count of the total number of objects in this connection, ignoring pagination.
// This allows a client to fetch the first five objects by passing "5" as the
// argument to "first", then fetch the total count so it could display "5 of 83",
// for example.`
}
})
});
const Pagination = new GraphQLInputObjectType({
name: 'Pagination',
fields: connectionArgs
});
export const UserConnection = connectionType;
export const UserEdge = edgeType;
export const UserPagination = Pagination;
import { GraphQLString } from "graphql";
import { connectionArgs } from "graphql-relay";
import connectionFromMongoCursor from "relay-mongodb-connection";
import infoToProjection from "graphql-mongodb-projection";
import { User } from "../../models";
import { UserConnection, UserPagination } from "./UserConnection";
export const users = {
type: UserConnection,
args: {
category: { type: GraphQLString },
pagination: { type: UserPagination }
},
async resolve(root, { category, pagination }, ctx, info) {
const { user } = ctx.state;
const hasCategory = category ? { category } : {};
const query = { ...hasCategory };
const projection = infoToProjection(info);
try {
const usersList = await connectionFromMongoCursor(
User.secureFind(user, query, projection),
pagination
);
if (!usersList) throw "not found";
const totalCount = await User.secureCount(user, query);
const userListWithTotalCount = {
...usersList,
totalCount
};
return userListWithTotalCount;
} catch (error) {
throw error;
}
}
};
export default users;
query {
users(pagination: {first: 3}) {
totalCount
edges {
node {
_id
}
}
}
}
{
"data": {
"users": {
"totalCount": 25,
"edges": [
{
"node": {
"_id": "58eba048307ce2316004bb2c"
}
},
{
"node": {
"_id": "5922c481ade5f823f48d69af"
}
},
{
"node": {
"_id": "5928372952ae8416ec532ef9"
}
}
]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment