简体   繁体   中英

Query dynamic schema using a JSON object - GraphQL .NET 6 PostgreSQL and HotChocolate

I need to develop a graphql server to query data directly from a JSON object. this JSON object is stored in a postgres database table as below.

在此处输入图像描述

This value field can be any JSON object. I don't have control over that. it's directly coming from a SharePoint server. I need to query this JSON object dynamically using graphql.

What I want here is to query JSON object and get only what I need instead of getting all the JSON data. for example like below

query {
  allBookings {
    id,
    listId
    widget {
      text  {
        name
        style
        onMouseUp
      }
    }
  }
}

currently, my result is this. 在此处输入图像描述

Technologies I am using

  • .NET 6
  • Postgresql
  • HotChocolate

this is my code so far.

[Table("bookings")]
public class Booking
{
    [Column(name: "id")]
    public int Id { get; set; }
    [Column(name: "list_id")]
    public Guid ListId { get; set; }
    [Column(name: "value", TypeName = "jsonb")]
    [GraphQLType(typeof(AnyType))]
    public string Value { get; set; }
}

public class BookingType : ObjectType<Booking>
{
    private readonly IDbContextFactory<DemoDBContext> _factory;

    public BookingType(IDbContextFactory<DemoDBContext> factory)
    {
        _factory = factory;
    }

    [Obsolete]
    protected override void Configure(IObjectTypeDescriptor<Booking> descriptor)
    {
        descriptor.Field(t => t.Id)
            .Type<NonNullType<IntType>>();
        descriptor.Field(t => t.ListId)
            .Type<NonNullType<UuidType>>();
        descriptor.Field(t => t.Value)
            .Type<AnyType>()
            .Resolver(context =>
            {
                var db = _factory.CreateDbContext();
                var value = context.Parent<Booking>().Value;
                return value;
            });
    }
}

public class Query
{
    private readonly IDbContextFactory<DemoDBContext> _factory;

    public Query(IDbContextFactory<DemoDBContext> factory)
    {

       _factory = factory;
    }

    public async Task<IEnumerable<Booking>> GetAllBookings()
    {
        using var context = await _factory.CreateDbContextAsync();

        var bookings = await context.Bookings.ToListAsync();
        return bookings;
    }

    public async Task<Booking> GetBooking(Guid id)
    {
        using var context = await _factory.CreateDbContextAsync();

        var booking = await context.Bookings.Where(x => x.ListId == id).FirstOrDefaultAsync();

        return booking;
    }
}

I've tried different methods but I don't have a clear idea to implement this kind of behavior or even is this possible to do.

if there's a better way of doing this please suggest me. Thanks all.

GraphQL will automatically filter out fields that are either not requested or not part of a model.

If you define your types as:

type Booking {
  id: ID!
  listID: String
  value: Widget
}
type Widget {
  text: SubWidget
}
type SubWidget {
  name: String
  style: String
  onMouseUp: String
}
query allBookings: [Booking]

In your resolver you're going to return an array of JSON objects corresponding to each Booking . If that JSON has fields that are not part of your type definitions they will not be returned. If some of the fields you ask for are missing then they will come back as undefined unless you make them non-nullable (ex: name: String! )

So you're most of the way there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM