Лучший шаблон для ручного анализа аргументов для оптимизации запросов в GraphQL dotnet

#graphql-dotnet

Вопрос:

У нас есть реализация GraphQL dotnet, расположенная поверх нашей существующей базы данных приложений.

 <PackageReference Include="GraphQL" Version="3.3.2" />
<PackageReference Include="GraphQL.SystemTextJson" Version="3.3.2" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Transports.WebSockets" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore.SystemTextJson" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Ui.Playground" Version="4.4.1" />
<PackageReference Include="GraphQL.Server.Authorization.AspNetCore" Version="4.4.1" />
 

У нас довольно взаимосвязанная структура данных, поэтому при запросе из некоторых наших полей верхнего уровня, включая некоторые их подполя, мы можем объединять большое количество таблиц. Однако не каждому запросу понадобятся все эти соединения.

Я надеялся, что смогу вручную проанализировать контекст.Аргументы в нашем запросе ObjectGraphType, когда я решаю его, чтобы исключить соединения, если конкретное подполе не запрашивается.

Очень простая версия этого на высоком уровне будет выглядеть следующим образом:

 Field<ListGraphType<OrganisationType>>(
"organisations",
resolve: context =>
{
    var retVal = database.Organisations();

    //Are we joining on employers?
    if(context.SubFields.ContainsKey("employers"))
    {
        retVal.Include(x => x.Employers.Where(x => x.Deleted != true))
                .ThenInclude(x => x.Departments.Where(x => x.Deleted != true));
    }

    return retVal;          
}
 

Где мы присоединяемся только к работодателям, если пользователь запросил это. Однако проблема в том, что у работодателей могут быть отделы, сотрудники, менеджеры и т. Д. И т. Д., И сами они могут иметь большое количество дополнительных свойств.

В настоящее время наш запрос присоединяется практически к каждой перестановке запроса, создавая действительно мощный SQL-запрос. Что является большой нагрузкой, если пользователь хочет только название организации и имя каждого работодателя.

Фильтрация на самом верхнем уровне достаточно проста (как показано выше), но я не могу понять, как выполнять запросы с этого момента, я просто, кажется, оказываюсь в бесконечном цикле детей… например:

 var employerSubField = context.SubFields["employers"];
var otherJoins = employerSubField.SelectionSet.Children.Where(x => x.Children)
 

Кажется, я не могу найти имя «где» = = «Сотрудники» или что-то в этом роде. Нужно ли мне разыгрывать GraphQL.Language.AST.указывает на что-то в какой-то момент? Когда я проверяю значения во время отладки, похоже, что я должен видеть значения, которые мне нужны. Но это не будет компилироваться.

 var deptsField = employerSubField.SelectionSet.Selections.Where(x => x.Name == "departments");
 

Отладочная информация

Ответ №1:

Я нашел следующий способ получить основную информацию, которую я затем могу легко проанализировать сам и добавить свою собственную пользовательскую логику.

 var query = context.Document.OriginalQuery.Substring(context.Document.OriginalQuery.IndexOf("{")).RemoveWhitespace();
 

ВОЗВРАТ:

 {organisations{id,name,employers{id,name,clientNotes,departments{id,name}}}}