graphql-platform
graphql-platform copied to clipboard
Filtering on nested objects with `HotChocolate.Data` package
Is there an existing issue for this?
- [X] I have searched the existing issues
Product
Hot Chocolate
Describe the bug
I apologize in advance if this is not the right location to ask this.
I've been having a hard time getting HotChocolate.Data filtering to work on nested objects. I was able to get the old package to work.
When using HotChocolate.Types.Filters package the following query works
query {
objectA (where: {code_in:[1000,2000]}) {
id
friendlyName
objectB(where: {name_contains:"Clean"}){
id
name
}
}
}
When using HotChocolate.Data package the nested (objectB) does not work only ObjectA filter works. The EF WHERE Clause is not generated.
query {
objectA (where: { id: { in: [1000,2000] } }) {
id
friendlyName
objectB(where: {name:{contains:"Clean"}}) {
id
name
}
}
}
Versions
HotChocolate.AspNetCore 13.2.1
HotChocolate.Data 13.2.1
HotChocolate.Data.EntityFramework 13.2.1
Microsoft.EntityFrameworkCore 7.0.7
Microsoft.EntityFrameworkCore.SqlServer 7.0.7
Steps to reproduce
- Create schema and implement filtering using
HotChocolate.Types.Filterspackage - Run query and make sure filtering works at multiple levels
- Remove
HotChocolate.Types.Filterspackage - Install
HotChocolate.Datapackage - Run same query with the same filtering using
HotChocolate.Datapackage
Relevant log output
No response
Additional Context?
No response
Version
13.2.1
Can you share some resolver code? also do you want to filter the list of objectA's by id and objectB.name or do you want to filter objectA by id and objectB by name ? do you want to do this in one or mutliple db calls?
I am having the same issues, hopefully this minimal setup can shed some light into the issue When removing the property from the DTO/POCO it will filter properly, in both scenarios the query will go through the Query and the Node methods.
public class ObjectA {
public int Id {get;set;}
//removing this property will allow subcollections to be filtered
public IEnumerable<ObjectB> Children {get;set;}
}
public class ObjectB {
public string Name {get;set;}
public virtual ObjectA Parent {get; set;}
}
[QueryType]
public static class ObjectAQueries {
[UseOffsetPaging]
[UseSorting]
[UseFiltering]
public static IQueryable<ObjectA> GetAs (DbContext dbContext){
return dbContext.A;
}
}
[ExtendsObjectType(typeOf(ObjectA))]
public static class ObjectANode {
[UseOffsetPaging]
[UseSorting]
[UseFiltering]
public static IQueryable<ObjectB> GetChildren([Parent] ObjectA parent, DbContext dbContext){
return dbContext.B.Where(p=> p.Parent.Id == parent.Id);
}
}
public class ObjectAType: ObjectType<ObjectA>{
protected override void Configure(IObjectTypeDescriptor<ObjectA> descriptor)
{
descriptor.BindFieldsExplicitly();
descriptor
.Field(f => f.Id)
.IsProjected(true);
descriptor
.Field(f => f.Children);
//removing the lambda in favor of a string representation will allow subcollections to be filtered
//Field("children");
}
}
I ran into the same issue but found that if I set the name of the IQueryable function to be different from the underlying class field filtering works correctly. So in the example above a dirty work around would be to do something like...
[ExtendsObjectType(typeOf(ObjectA))]
public static class ObjectANode {
[UseOffsetPaging]
[UseSorting]
[UseFiltering]
[GraphQLName("childrenQuery")]
public static IQueryable<ObjectB> GetChildren([Parent] ObjectA parent, DbContext dbContext){
return dbContext.B.Where(p=> p.Parent.Id == parent.Id);
}
}
Changing the node name to something different than the name of the class field worked for me. You will have both nodes in the graph but filtering works on child nodes using childrenQueryable.
I'm having a similar issue. Paging, sorting, filtering and projection work at the root level but not on nested objects. I've attached a .zip to illustrate the issue. I asked on Slack originally (https://hotchocolategraphql.slack.com/archives/CD9TNKT8T/p1718892458760509) and @michaelstaib replied initially and asked me to supply a repro but he hasn't responded since then (probably extremely busy) so I'm mentioning it here too.
Issuing he following query will allow paging/sorting/filtering on the Products but on the nested Options or Option Items.
{
products(order: {id: ASC}) {
items {
id
name
options
( # take: 1
where: {name: {eq: "option-a"}},
order: {id: DESC}
) {
items {
id
name
optionItems(order: {price: DESC}) {
items {
id
name
price
}
}
}
}
description
}
}
}
i have the same issue
I was able to filter on the child property by adding the [UseFiltering] attribute to the Entity.
public class Parent
{
[UseFiltering]
public ICollection<Child> Children { get; set; }
}
public class Child
{
public string Name { get; set; }
}
public class Query
{
[UseProjection]
[UseFiltering]
public IQueryable<Parent> GetParents([Service(ServiceKind.Synchronized)] DataContext context)
{
return context.Parents.AsNoTracking();
}
}
I still have the same issues, even when adding [UseFiltering] on the child property as suggested.
The bug is still present in v15.0.3
Its because of the old way we did projections... if you move to the new projections engine you wont have this issue anymore.
The new GreenDonut.Data API bring together DataLoader, projections, filtering and sorting to get more predictable performance and more control over the whole query. At the moment this is available for EF Core and we are working on MongoDB support.
https://www.youtube.com/watch?v=FhNK7KMAnXc