Hotchocolate Filter by BsonExtraElements

Hotchocolate Filter by BsonExtraElements


0

We have next entity:

public class Product
{
    public Guid Id { get; set; }

    public string Name { get; set; } = string.Empty;
  
    [BsonExtraElements]
    public Dictionary<string, object?> AdditionalData { get; set; } = new();
}

This entity can have many dynamic data that can be stored inside AdditionalData property. Using attribute BsonExtraElements we can save these data to MongoDb perfectly. Our data will be stored as separated properties. It is exactly what we want to save on Storage Level.

After it we implemented all steps hat described in instruction.

So we designed next ObjectType:

public class ProductType : ObjectType<Product>
{
    private readonly List<EntityFieldDescriptor> _fields;

    public ProductType(ICollection<EntityFieldDescriptor> fields)
    {
        // There provided or "dynamic" properties for specific entity
        _fields = fields;
    }

    protected override void Configure(IObjectTypeDescriptor<Product> descriptor)
    {
        descriptor.Field(f => f.Id).ID().Name("id");       
        descriptor.Field(f => f.Name).Name("name");       
        descriptor.Ignore(entity => entity.AdditionalData);

        foreach (var field in _fields)
        {
            descriptor
                .Field(field.Name)
                .Type(Type.GetType(field.ValueType)!)
                .Resolve(resolver => resolver.Parent<Product>().AdditionalData.GetValueOrDefault(field.Name));
        }

        descriptor.BindFieldsImplicitly();
    }
}

And query:

public partial class Query
{
    [UseProjection]
    [UseSorting]
    [UseFiltering]
    public IExecutable<Product> GetProducts(
        [Service] IMongoCollection<Product> collection)
    {
        return collection.AsExecutable();
    }

    [UseFirstOrDefault]
    public IExecutable<Product> GetProductById(
        [Service] IMongoCollection<Product> collection,
        [ID(nameof(Product))] Guid id)
    {
        return collection.Find(x => x.Id == id).AsExecutable();
    }
}

And service registration:

services.AddGraphQLServer()
    .AddType<ProductType>()
    .AddQueryType<Query>()
    .AddMongoDbFiltering()
    .AddMongoDbSorting()
    .AddMongoDbProjections()
    .AddMongoDbPagingProviders();

Using this configuration we can work with predefined properties very well.
We can run next query perfectly:

query { 
  products(where: { name: { eq: "test" }}) {
      id,
      material # It is our "dynamic" field
  }
}

Our goal to use "dynamic" field inside where clause. Example: where: {material: { eq: "cuprum" }}

Of course our filter schema do not know nothing about "dynamic" fields. So we defined next FilterInputType very similar to ObjectType:

public class ProductFilterType : FilterInputType<Product>
{
    private readonly List<EntityFieldDescriptor> _fields;

    public ProductFilterType(ICollection<EntityFieldDescriptor> collection)
    {
        // There provided or "dynamic" properties for specific entity
        _fields = fields;
    }

    protected override void Configure(IFilterInputTypeDescriptor<Product> descriptor)
    {
        descriptor.Field(f => f.Code).Name("code");
        descriptor.Ignore(entity => entity.AdditionalData);

        foreach (var field in _fields)
        {
            descriptor.Field(field.Name).Type(typeof(StringOperationFilterInputType));
        }

        descriptor.BindFieldsImplicitly();
    }
}

After creation of this FilterInputType we will be able to run our GraphQL query to server.
But when Hotchocolate run our query then we have an error:

Hotchocolate Filter by BsonExtraElements

Is it possible to use filtration/sorting/pagination of BsonExtraElements using Hotchocolate library?

Will be gratefull to any help!


Load 2 more related questions


Show fewer related questions

0



Leave a Reply

Your email address will not be published. Required fields are marked *