graphql-mongodb-select
v0.0.4
Published
Graphql plugin to automatically build MongoDB projections and populate objects from GraphQL queries
Maintainers
Readme
graphql-mongodb-select
A Graphql plugin designed to automatically translate GraphQL query selections into MongoDB projections ($project) and Mongoose populate options. Optimize your database calls by fetching exactly what the client requests, completely avoiding over-fetching on database calls.
Features
- 🚀 Automatic Projection: Converts GraphQL requested fields into MongoDB
$projectobjects. - 🔗 Deep Population: Automatically detects nested GraphQL fields and constructs Mongoose
populatearrays. - 🛠️ Custom Exclusions: Easily exclude specific paths (like
pageInfo, pagination cursors, etc.) from being projected. - ⚡ Zero Setup on Resolvers: Once added to your Apollo Server context, your resolvers can simply use the generated projection and populate objects directly in Mongoose queries.
Installation
Using Yarn:
yarn add graphql-mongodb-select
Using npm:
npm install graphql-mongodb-select
Prerequisites
- Node.js >= 18
@apollo/server>= 5.0.0 (Also works with v4)graphql>= 16.0.0
Usage
1. Define the Directive in your Schema
Add the @smartFetch directive to your GraphQL schema. Apply it to the fields you want to automatically resolve.
# schema.graphql
directive @smartFetch(field: String) on FIELD_DEFINITION
type Query {
users: [User!]! @smartFetch
}2. Extend your Apollo Context
Ensure your Apollo Server context includes the properties where the plugin will inject the $project and populate data.
// context.ts
import { AutoProjectAndPopulateContext } from 'graphql-mongodb-select'
export interface MyContext extends AutoProjectAndPopulateContext {
// ... your other context types (user, token, etc.)
}3. Add the Plugin to Apollo Server
Register the createSmartFetchPlugin in your Apollo Server initialization. You can pass options like excludePaths to ignore certain GraphQL fields that do not map to your database.
// server.ts
import { ApolloServer } from '@apollo/server'
import { createSmartFetchPlugin } from 'graphql-mongodb-select'
import { typeDefs, resolvers } from './schema'
import { MyContext } from './context'
const server = new ApolloServer<MyContext>({
typeDefs,
resolvers,
plugins: [createSmartFetchPlugin({ excludePaths: ['pageInfo', 'totalCount'] })],
})4. Use in Resolvers
In your GraphQL resolvers, access the generated $project and populate objects from the context and pass them to your Mongoose queries.
// resolvers.ts
export const resolvers = {
Query: {
users: async (_, args, context) => {
const { $project, populate } = context
const { $project, populate } = context
const result = await UserModel.find().select($project).populate(populate).exec()
return result
},
},
}How it Works
When a query is executed, the plugin intercepts the willResolveField event. It parses the GraphQL AST to determine exactly which fields the client requested.
- Primitive Fields: Mapped directly to
$project: { fieldName: 1 }. - Nested Objects: Mapped to Mongoose
populatearrays with specificselectstrings. - Fragments: Automatically resolved and merged into the selection tree.
License
MIT
