graphql-platform
graphql-platform copied to clipboard
MongoDB integration not filtering child collections
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
I have a simple document that has a collection (modelReferences), and within it that I would like to filter the modelReferences by their Id property, however filtering at these child collections does not appear to work.
Note: When the exact same model is configured with the EFCore integration it works as expected, but not using MongoDb integratation.
Here is a simple example, of an unfiltered query on modelReferences child collection:
{
gatewayServicesGatewayDefinitions {
items{
name name
modelReferences {
id
}
}
}
}
Resultant data :
{
"data": {
"gatewayServicesGatewayDefinitions": {
"items": [
{
"name": "Test",
"modelReferences": [
{
"id": "f00554bc-fcef-417c-baee-9234534cb6bd"
}
]
}
]
}
}
}
And with the filter in which the id does not exist:"
{
gatewayServicesGatewayDefinitions {
items{
name name
modelReferences (where: {id:{eq:"f00554bc-fcef-417c-baee-9234534cb6be"}}) {
id
}
}
}
}
Should return no data modelReferences collection items, as that ID does not exist, however it returns everything as if is unfiltered:
{
"data": {
"gatewayServicesGatewayDefinitions": {
"items": [
{
"name": "Test",
"modelReferences": [
{
"id": "f00554bc-fcef-417c-baee-9234534cb6bd"
}
]
}
]
}
}
}
Here is the GraphQL configuration:
builder.Services.AddGraphQLServer()
.AddAuthorization()
.AddType<ErrorResponse>()
.AddType<AggregateEvent>()
.AddType<GatewayServicesGatewayDefinitionSM.GatewayDefinition>()
.AddQueryType()
.AddTypeExtension<GatewayDefinitionGraphQLQuery>()
.AddMutationType()
.AddTypeExtension<GatewayDefinitionGraphQLMutation>()
.AddMongoDbFiltering()
.AddMongoDbSorting()
.AddMongoDbProjections()
.AddMongoDbPagingProviders();
Here is the Query Definition:
public partial class GatewayDefinitionGraphQLQuery
{
[UseFirstOrDefault]
public IExecutable<GatewayServicesGatewayDefinitionSM.GatewayDefinition> GetGatewayServicesGatewayDefinition([Service] IMongoCollection<GatewayServicesGatewayDefinitionSM.GatewayDefinition> collection, Guid id)
{
return collection.Find(x => x.Id == id).AsExecutable();
}
[UseOffsetPaging(IncludeTotalCount = false, DefaultPageSize = 10)]
[UseProjection]
[UseSorting]
[UseFiltering]
public IExecutable<GatewayServicesGatewayDefinitionSM.GatewayDefinition> GetGatewayServicesGatewayDefinitions([Service] IMongoCollection<GatewayServicesGatewayDefinitionSM.GatewayDefinition> collection)
{
return collection.AsExecutable();
}
}
Here is the model definition:
[HotChocolate.AspNetCore.Authorization.Authorize]
[GraphQLName("gatewayServices_gatewayDefinition")]
[Serializable]
[BsonIgnoreExtraElements]
public class GatewayDefinition
{
public string Name { get; set; } = string.Empty;
[HotChocolate.Data.UseFiltering]
[HotChocolate.Data.UseSorting]
public List<GatewayServicesGatewayDefinitionSM.ModelReference> ModelReferences { get; set; } = new();
[BsonId(IdGenerator = typeof(GuidGenerator)), BsonRepresentation(BsonType.String)]
[DataMember(Name = "id")]
public System.Guid? Id { get; set; } = Guid.Empty;
}
Here is the Node Resolver:
public class GatewayDefinitionNodeResolver
{
public Task<GatewayServicesGatewayDefinitionSM.GatewayDefinition> ResolveAsync([Service] IMongoCollection<GatewayServicesGatewayDefinitionSM.GatewayDefinition> collection, Guid id)
{
return collection.Find(x => x.Id == id).FirstOrDefaultAsync();
}
}
Here is the related child type, "ModelRerference" that I am trying to filter:
[HotChocolate.AspNetCore.Authorization.Authorize]
[GraphQLName("gatewayServices_modelReference")]
[Serializable]
[BsonIgnoreExtraElements]
public class ModelReference
{
public System.Guid DomainModelId { get; set; } = Guid.Empty;
public int Depth { get; set; } = 2;
[BsonId(IdGenerator = typeof(GuidGenerator)), BsonRepresentation(BsonType.String)]
public System.Guid? Id { get; set; } = Guid.Empty;
}
Steps to reproduce
- Apply same code as above
Relevant log output
No response
Additional Context?
No response
Product
Hot Chocolate
Version
12.8.2
I included the definition of the ModelReference (child collection).
@PascalSenn , I was told you are the maintainer of the MongoDB integration library. Please see the above issue and let me know if you require further information.
Is filtering of children not possible in the MongoDB integration?
If yes and you can't provide me with an answer, can you at least provide me with hints as to where to look within the MongoDB integration source code so that I can try to figure this out. This is a major issue for us at the present time.
Thank you in advance, John
@jkears at the moment this is not possible. How would the mongo query look like if you would issue one? Also, do you mind filtering in memory? this would be possbile.
@PascalSenn , thanks for your prompt reply. I thought we were doing something wrong.
Yes, filtering in memory would be fine for most of our scenarios, how would I integrate this via a GraphQL query?
@PascalSenn, this seems to be the way that you'd filter it.
@jkears okok. so opting for the aggregation pipeline.. i mean, could work. Has other issues of course ;) like scalability of queries. But depending on the document you receive this might not even be necessary.
so try this
services.AddMongoDbFiltering(); //ordermatters
services.AddFiltering("queryable")
and then do
[HotChocolate.Data.UseFiltering("queryable")]
[HotChocolate.Data.UseSorting]
public List<GatewayServicesGatewayDefinitionSM.ModelReference> ModelReferences { get; set; } = new();
@PascalSenn
I swear I was able to add a string previously, but now I get this error ..
error CS1503: Argument 1: cannot convert from 'string' to 'System.Type?'
Here are my package references...
mybad [UseFiltering(Scope = "queryable")]
@PascalSenn Yes I had also figure that I needed to define scope.
I also have to change this to
.AddMongoDbFiltering()
.AddFiltering("queryable")
to this ..'
.AddMongoDbFiltering("queryable")
.AddFiltering()
as when it was complaining that it was missing AddFiltering()
However, now it is complaining ...
1. The name gatewayServices_modelReferenceFilterInput
was already registered by another type. (HotChocolate.Data.Filters.FilterInputType<NextWare.CoreServices.SharedModels.GatewayServices.GatewayDefinitionAggregate.Models.ModelReference>)
@PascalSenn I am still not getting this to work...
As mentioned, when I attempted to configure filtering this way....
.AddMongoDbFiltering()
.AddFiltering("queryable")
I get this exception at startup ...
[nextwarecoreservicesgatewayservices_825fad40-c]: 1. No default filter convention found. Call `AddFiltering()` on the schema builder.
[nextwarecoreservicesgatewayservices_825fad40-c]: (HotChocolate.Types.ObjectType<NextWare.CoreServices.SharedModels.GatewayServices.GatewayDefinitionAggregate.Models.GatewayDefinition>)
and if I try it this way ...
.AddMongoDbFiltering("queryable")
.AddFiltering()
I get this exception at startup...
1. The name gatewayServices_modelReferenceFilterInput was already registered by another type. (HotChocolate.Data.Filters.FilterInputType<NextWare.CoreServices.SharedModels.GatewayServices.GatewayDefinitionAggregate.Models.ModelReference>)
We are desperately trying to get this working, can you please advise what it is I am doing incorrectly? Many thanks!
@PascalSenn , can you please help me resolve this issue?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Exact same issue as @jkears . Is there a fix? I couldn't get it working even as much as https://github.com/ChilliCream/graphql-platform/issues/5622 describes.
Following the callout: https://chilly-relay-docs.netlify.app/docs/hotchocolate/v11/integrations/mongodb/#filtering
My ServiceCollection.cs has this:
.AddMongoDbFiltering("queryable")
.AddMongoDbSorting()
.AddMongoDbProjections()
.UseDefaultPipeline()
.AddFiltering()
.AddSorting()
My query has this:
[UsePaging]
[UseFiltering(Scope ="queryable")]
[UseSorting]
[Authorize(Policy = Policy.Name.LicensedUsersOnly)]
[GraphQLDescription("Get all sites")]
public async Task<IEnumerable<Site?>> GetSitesAsync()
Additionally I injected the IResolverContext to the query and attempted to filter like this:
var result = sites.Filter(context)
where context is the IResolverContext. It throws an exception here: Filtering was not found. Register filtering with [UseFiltering] or descriptor.UseFiltering()
. If I remove the Scope from [UseFiltering], there is no error, but obviously the filter is not attempted.