在 GraphQL 中使用查询结果作为下一级别的参数 [英] Use Query Result as Argument in Next Level in GraphQL

查看:39
本文介绍了在 GraphQL 中使用查询结果作为下一级别的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

之前已经讨论过这个问题,但这是其中之一,因为有如此多的分散讨论导致了各种提议的黑客",我很难确定我应该做什么.

This has been discussed a bit before, but it's one of those things where there is so much scattered discussion resulting in various proposed "hacks" that I'm having a hard time determining what I should do.

我想将查询的结果用作另一个嵌套查询的参数.

I would like to use the result of a query as an argument for another nested query.

query {
  allStudents {
    nodes {
      courseAssessmentInfoByCourse(courseId: "2b0df865-d7c6-4c96-9f10-992cd409dedb") {
        weightedMarkAverage
        // getting result for specific course is easy enough
      }
      coursesByStudentCourseStudentIdAndCourseId {
        nodes {
          name
          // would like to be able to do something like this
          // to get a list of all the courses and their respective
          // assessment infos
          assessmentInfoByStudentId (studentId: student_node.studentId) {
            weightedMarkAverage
          }
        }
      }
    }
  }
}

是否有一种被认为是最佳实践的方法?现在是否有一种标准的方法可以将其内置到 GraphQL 中?

Is there a way of doing this that is considered to be best practice? Is there a standard way to do it built into GraphQL now?

感谢您的帮助!

推荐答案

在 GraphQL 文档中替换值的唯一方法是通过变量,这些必须在您的操作定义中声明,然后作为您的文档的一部分包含在您的文档中要求.在同一文档中没有引用以前解析的值的固有方法.

The only means to substitute values in a GraphQL document is through variables, and these must be declared in your operation definition and then included alongside your document as part of your request. There is no inherent way to reference previously resolved values within the same document.

如果您认为需要此功能,通常首先是架构设计不佳的症状.下面是一些改进架构的建议,前提是您可以对其进行控制.

If you get to a point where you think you need this functionality, it's generally a symptom of poor schema design in the first place. What follows are some suggestions for improving your schema, assuming you have control over that.

例如,您至少可以完全消除 assessmentInfoByStudentId 上的 studentId 参数.coursesByStudentCourseStudentIdAndCourseId 是学生节点上的一个字段,因此它的解析器已经可以访问学生的 id.它可以将此信息传递给每个课程节点,然后由 assessmentInfoByStudentId 使用.

For example, minimally, you could eliminate the studentId argument on assessmentInfoByStudentId altogether. coursesByStudentCourseStudentIdAndCourseId is a field on the student node, so its resolver can already access the student's id. It can pass this information down to each course node, which can then be used by assessmentInfoByStudentId.

也就是说,您最好重新考虑一下您是如何建立连接的.我不知道你的底层存储层是什么样的,或者你的客户需要数据的形状,所以很难提出任何具体的建议.但是,为了举例,我们假设我们有三种类型——CourseStudentAssessmentInfo.一个Course有很多Students,一个Student有很多Courses,还有一个AssessmentInfo有一个 Student 和一个 Course.

That said, you're probably better off totally rethinking how you've got your connections set up. I don't know what your underlying storage layer looks like, or the shape your client needs the data to be in, so it's hard to make any specific recommendations. However, for the sake of example, let's assume we have three types -- Course, Student and AssessmentInfo. A Course has many Students, a Student has many Courses, and an AssessmentInfo has a single Student and a single Course.

我们可能会将所有三个实体都公开为根级查询:

We might expose all three entities as root level queries:

query {
  allStudents {
    # fields
  }
  allCourses {
    # fields
  }
  allAssessmentInfos {
    # fields
  }
}

每个节点都可以连接到其他两种类型:

Each node could have a connection to the other two types:

query {
  allStudents {
    courses {
      edges {
        node {
          id
        }
      }
    }
    assessmentInfos {
      edges {
        node {
          id
        }
      }
    }

  }
}

如果我们想获取所有学生,并且每个学生都知道他/她正在修什么课程以及他/她对该课程的加权平均分,我们可以编写如下查询:

If we want to fetch all students, and for each student know what courses s/he is taking and his/her weighted mark average for that course, we can then write a query like:

query {
  allStudents {
    assessmentInfos {
      edges {
        node {
          id
          course {
            id
            name
          }
        }
      }
    }

  }
}

同样,这个确切的模式可能不适用于您的特定用例,但它应该让您了解如何从不同的角度解决您的问题.设计架构时的更多提示:

Again, this exact schema might not work for your specific use case but it should give you an idea around how you can approach your problem from a different angle. A couple more tips when designing a schema:

  • 在连接字段上添加过滤器参数,而不是为您需要涵盖的每个场景创建单独的字段.Student 类型上的单个 courses 字段可以有多种参数,例如 semestercampusisPassing -- 这比创建不同的字段(如 coursesBySemestercoursesByCampus 等)更简洁、更灵活.
  • 如果您正在处理诸如平均值、最小值、最大值等聚合值.将这些值公开为每个连接类型的字段可能是有意义的,就像 count 字段一样有时可与 nodes 字段一起使用.有一个(提案)[https://github.com/prisma/prisma/issues/1312] 对于 Prisma,它说明了处理这些聚合值的一种相当简洁的方法.做这样的事情意味着如果你已经有,例如,一个 Assessment 类型,一个连接字段可能足以公开关于该类型的聚合数据(如平均成绩),而无需公开一个单独的 AssessmentInfo 类型.
  • 过滤相对简单,分组有点困难.如果您确实发现需要按特定字段分组的连接节点,最好再次通过在连接本身上公开一个附加字段来完成(就像 Gatsby 那样)[https://www.gatsbyjs.org/docs/graphql-reference/#group].
  • Add filter arguments on connection fields, instead of creating separate fields for each scenario you need to cover. A single courses field on a Student type can have a variety of arguments like semester, campus or isPassing -- this is cleaner and more flexible than creating different fields like coursesBySemester, coursesByCampus, etc.
  • If you're dealing with aggregate values like average, min, max, etc. it might make sense to expose those values as fields on each connection type, in the same way a count field is sometimes available alongside the nodes field. There's a (proposal)[https://github.com/prisma/prisma/issues/1312] for Prisma that illustrates one fairly neat way to do handle these aggregate values. Doing something like this would mean if you already have, for example, an Assessment type, a connection field might be sufficient to expose aggregate data about that type (like grade averages) without needing to expose a separate AssessmentInfo type.
  • Filtering is relatively straightforward, grouping is a bit tougher. If you do find that you need the nodes of a connection grouped by a particular field, again this may be best done by exposing an additional field on the connection itself, (like Gatsby does it)[https://www.gatsbyjs.org/docs/graphql-reference/#group].

这篇关于在 GraphQL 中使用查询结果作为下一级别的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆