I'm looking to use Hot Chocolate's Filtering to query against one data type; and then transform that filtered output to another type before returning it as an IQueryable. But I can't seem to find anyway to capture the filter input to start my transform.
Here's an example of what I'm trying to accomplish:
Given the data classes
public class TypeA
{
public string Foo { get; set; }
}
public class TypeB
{
public string Fizz { get; set; }
public string Buzz { get; set; }
}
I want to be able to create a query endpoint like
public class Query
{
[UseDbContext(typeof(DbContext))]
[UseFiltering(typeof(TypeA))]
public IQueryable<TypeB> GetTypeB(
[ScopedService] DbContext context,
[SomeAttributeToCaptureTheFilter] Filter filter) // <- this is the line I'm trying to figure out
{
IQueryable<TypeA> filteredTypeAs = context.TypeA.Filter(filter); // .Filter() doesn't exist, its just for example.
IQueryable<TypeB> filteredTypeBs;
/* Complex transformation logic that populates 'filteredTypeBs'
* requiring the 'filteredTypeAs' and additional Data from
* the database to complete. */
return filteredTypeBs;
}
}
Against which, I can use a GraphQL Query like the following
query {
typeB(where: { foo: { eq: "bar" } }) {
fizz
buzz
}
}
where: { foo: { eq: "bar" } }
Being the filter against TypeA
, and the
typeB {
fizz
buzz
}
pulling the content from the transformed TypeB
.
Using [UseFiltering(typeof(TypeA))]
does work, It sets up the schema to act as I want.
What I'm looking for is something to the effect of the line [SomeAttributeToCaptureTheFilter] Filter filter
. Just some way of capturing the filter and applying it to the data within the DbContext.
I will also say I'm very new to GraphQL in general, so how I'm approaching this problem may be entirely wrong. Any advice would be helpful.
Answering my own question for anyone who may stumble upon this in the future.
The answer was in the HotChocolate.Data
package. It contains Filter
extensions for IQueryable<T>
and IEnumerable<T>
; that allow you to run the filter inline by passing an IResolverContext
. I couldn't find references to any of this in the documentation, I came across it in an example about data aggregation: https://github.com/ChilliCream/hotchocolate/issues/924#issuecomment-921793977
This is essentially what my final query method looked like:
using HotChocolate.Data;
using HotChocolate.Data.Filters.Expressions;
public class Query
{
[UseDbContext(typeof(DbContext))]
[UseFiltering(typeof(TypeA))]
public IQueryable<TypeB> GetTypeB(
[ScopedService] DbContext context,
IResolverContext resolverContext)
{
IQueryable<TypeA> filteredTypeAs = context.TypeA.Filter(resolverContext);
IQueryable<TypeB> filteredTypeBs;
/* Complex transformation logic that populates 'filteredTypeBs'
* requiring the 'filteredTypeAs' and additional Data from
* the database to complete. */
return filteredTypeBs;
}
}
I know my example's a bit esoteric, but the point of this is that it opens up access to a filtered version of the results within the query method itself. This allows for a whole world of possibilities when it comes to data aggregation/manipulation; while still taking advantage of the HotChocolate's built in functionality.
As a side note there also appears to be a Sort
extension, which is the equivalent for [UseSorting]
.