MongoDB
Learn how to integrate MongoDB with Hot Chocolate v16, including filtering, sorting, projections, and pagination.
Hot Chocolate has a data integration for MongoDB. With this integration, you can translate paging, filtering, sorting, and projections directly into native MongoDB queries.
You can find an example project in Hot Chocolate Examples.
Get Started
Install the HotChocolate.Data.MongoDb package:
dotnet add package HotChocolate.Data.MongoDbHotChocolate.* packages need to have the same version.MongoExecutable
The integration builds around IExecutable<T>. The AsExecutable extension method is available on IMongoCollection<T>, IAggregateFluent<T>, and IFindFluent<T>. The execution engine picks up the IExecutable and executes it efficiently. You can use any aggregation or find pipeline before calling AsExecutable.
[UsePaging][UseProjection][UseSorting][UseFiltering]public IExecutable<Person> GetPersons(IMongoCollection<Person> collection){ return collection.AsExecutable();}
[UseFirstOrDefault]public IExecutable<Person> GetPersonById( IMongoCollection<Person> collection, Guid id){ return collection.Find(x => x.Id == id).AsExecutable();}
Filtering
Register the MongoDB filtering convention on the schema builder:
builder .AddGraphQL() .AddQueryType<Query>() .AddMongoDbFiltering();
To use MongoDB filtering alongside
IQueryable/IEnumerable, register the MongoDB convention under a different scope:AddMongoDbFiltering("yourScope"). Then specify the scope on each resolver:[UseFiltering(Scope = "yourScope")].
Filters are converted to BsonDocuments and applied to the executable.
GraphQL Query:
query GetPersons { persons( where: { name: { eq: "Yorker Shorton" } addresses: { some: { street: { eq: "04 Leroy Trail" } } } } ) { name addresses { street city } }}
Mongo Query:
{ "find": "person", "filter": { "Name": { "$eq": "Yorker Shorton" }, "Addresses": { "$elemMatch": { "Street": { "$eq": "04 Leroy Trail" } } } }}
Sorting
Register the MongoDB sorting convention on the schema builder:
builder .AddGraphQL() .AddQueryType<Query>() .AddMongoDbSorting();
To use MongoDB sorting alongside
IQueryable/IEnumerable, register the MongoDB convention under a different scope:AddMongoDbSorting("yourScope"). Then specify the scope on each resolver:[UseSorting(Scope = "yourScope")].
Sorting is converted to BsonDocuments and applied to the executable.
GraphQL Query:
query GetPersons { persons(order: [{ name: ASC }, { mainAddress: { city: DESC } }]) { name addresses { street city } }}
Mongo Query:
{ "find": "person", "filter": {}, "sort": { "Name": 1, "MainAddress.City": -1 }}
Projections
Register the MongoDB projection convention on the schema builder:
builder .AddGraphQL() .AddQueryType<Query>() .AddMongoDbProjections();
To use MongoDB projections alongside
IQueryable/IEnumerable, register the MongoDB convention under a different scope:AddMongoDbProjections("yourScope"). Then specify the scope on each resolver:[UseProjection(Scope = "yourScope")].
Projections do not always improve performance. Even though MongoDB processes and transfers less data, projections can sometimes harm query performance. See this article by Tek Loon for guidance on when to use them.
GraphQL Query:
query GetPersons { persons { name addresses { city } }}
Mongo Query:
{ "find": "person", "filter": {}, "projection": { "Addresses.City": 1, "Name": 1 }}
Paging
Register the MongoDB-specific pagination providers:
builder .AddGraphQL() .AddMongoDbPagingProviders();
Learn more about pagination providers
Cursor Pagination
Annotate your resolver with [UsePaging] or .UsePaging() to use cursor-based pagination:
[UsePaging]public IExecutable<Person> GetPersons(IMongoCollection<Person> collection){ return collection.AsExecutable();}
Example query:
query GetPersons { persons(first: 50, after: "OTk=") { nodes { name addresses { city } } pageInfo { endCursor hasNextPage hasPreviousPage startCursor } }}
FirstOrDefault / SingleOrDefault
To return a single object from a collection, use the UseFirstOrDefault or UseSingleOrDefault middleware. Hot Chocolate rewrites the field type from a list to an object type.
[UseFirstOrDefault]public IExecutable<Person> GetPersonById( IMongoCollection<Person> collection, Guid id){ return collection.Find(x => x.Id == id).AsExecutable();}
Next Steps
- Pagination for pagination setup
- Filtering for filtering concepts
- Executable for the
IExecutableabstraction