【问题标题】:Prevent joining table if no field selected in GraphQL如果在 GraphQL 中未选择任何字段,则阻止加入表
【发布时间】:2019-03-06 16:41:24
【问题描述】:

我是 GraphQL 的新手。

目前,我有一个查询定义,用于搜索 students 及其参与的 classes

var studentsQueryArguments = new QueryArguments();
            studentsQueryArguments.Add(new QueryArgument<ListGraphType<IntGraphType>> { Name = "ids", Description = "Student indexes." });
            studentsQueryArguments.Add(new QueryArgument<RangeModelType<double?, double?>> {Name = "age", Description = "Age range of student."});
            Field<ListGraphType<StudentType>>(
                "students",
                arguments: studentsQueryArguments,
                resolve: context =>
                {
                    var students = relationalDbContext.Students.AsQueryable();
                    var classes = relationalDbContext.Classes.AsQueryable();
                    var participatedClasses = relationalDbContext.StudentInClasses.AsQueryable();

                    var ids = context.GetArgument<List<int>>("ids");
                    var age = context.GetArgument<RangeModel<double?, double?>>("age");

                    if (ids != null)
                        students = students.Where(x => ids.Contains(x.Id));

                    if (age != null)
                    {
                        var from = age.From;
                        var to = age.To;

                        if (from != null)
                            students = students.Where(x => x.Age >= from);

                        if (to != null)
                            students = students.Where(x => x.Age <= to);
                    }

                    var results = (from student in students
                        select new StudentViewModel
                        {
                            Id = student.Id,
                            Age = student.Age,
                            FullName = student.FullName,
                            Photo = student.Photo,
                            Classes = from participatedClass in participatedClasses
                                from oClass in classes
                                where participatedClass.StudentId == student.Id &&
                                      participatedClass.ClassId == oClass.Id
                                select new ClassViewModel
                                {
                                    Id = oClass.Id,
                                    ClosingHour = oClass.ClosingHour,
                                    Name = oClass.Name,
                                    OpeningHour = oClass.OpeningHour
                                }
                        });

                    return results;
                });

在上面的代码中,我加入了 StudentClass。 用查询

{
  students(ids: [1, 2, 3]) {
    id
    age
    classes {
      name
      openingHour
      closingHour
    }
  }
}

学生和他们的班级被返回。没关系。

我想要的是当我使用这个查询时:

{
  students(ids: [1, 2, 3]) {
    id
    age
  }
}

我的应用不会将Student加入Class,而只会返回Student信息。

有可能吗?

谢谢,

【问题讨论】:

    标签: c# graphql asp.net-core-2.0


    【解决方案1】:

    我做了一个超酷的扩展方法,它返回选择是否包含在 GraphQL 查询中。 如果选择中存在导航属性,请将其包含到您的查询中。


    扩展方法

    using System;
    using System.Linq;
    using GraphQL.Language.AST;
    using GraphQL.Types;    
    
    public static class ContextExtensions
    {
        /// <summary>
        /// Returns true if the given fieldSelector exists in the selection of the query.
        /// </summary>
        /// <param name="context">The working context</param>
        /// <param name="fieldSelector">The query of the field selector. For example items:organizationUnits:displayName</param>
        /// <param name="namespaceSeperator">The seperator character of the fieldSelector. Default is :</param>
        /// <returns></returns>
        public static bool HasSelectionField(this ResolveFieldContext<object> context, string fieldSelector, char namespaceSeperator = ':')
        {
            if (string.IsNullOrWhiteSpace(fieldSelector))
            {
                return false;
            }
    
            if (context.SubFields == null)
            {
                return false;
            }
    
            var fragments = fieldSelector.Split(new[] { namespaceSeperator }, StringSplitOptions.RemoveEmptyEntries);
    
            if (fragments.Length == 1)
            {
                return context.SubFields.ContainsKey(fragments[0]);
            }
    
            if (context.SubFields[fragments[0]] == null)
            {
                return false;
            }
    
            if (context.SubFields[fragments[0]].SelectionSet == null)
            {
                return false;
            }
    
            if (context.SubFields[fragments[0]].SelectionSet.Selections == null)
            {
                return false;
            }
    
    
            var selections = context.SubFields[fragments[0]].SelectionSet.Selections;
    
            for (var i = 1; i < fragments.Length; i++)
            {
                if (selections == null)
                {
                    return false;
                }
    
                var field = selections.Select(selection => (Field)selection).FirstOrDefault(f => f.Name == fragments[i]);
                if (field == null)
                {
                    return false;
                }
    
                if (i == fragments.Length - 1)
                {
                    return true;
                }
    
                selections = field.SelectionSet?.Selections;
            }
    
            return true;
        }
    }
    

    用法

    protected override async Task<PagedResultDto<UserDto>> Resolve(ResolveFieldContext<object> context)
    {
        var total_count_exists = context.HasSelectionField("totalCount"); //true
        var items_name_exists = context.HasSelectionField("items:name"); //true
        var items_roles_name_exists = context.HasSelectionField("items:roles:name"); //true
        var items_organizationUnits_displayName_exists = context.HasSelectionField("items:organizationUnits:displayName"); //true
        var items_organizationUnits_xyz_exists = context.HasSelectionField("items:organizationUnits:xyz"); //false
    }
    

    示例查询

    query MyQuery {
      users(id: 1) {
        totalCount
        items {
          name
          surname
    
          roles {
            id
            name
            displayName
          }
    
          organizationUnits {
            id
            code
            displayName
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-04
      • 2014-10-24
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      • 2017-11-18
      • 2018-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多