Use Query Result as Argument in Next Level in GraphQL

前端 未结 1 1465
花落未央
花落未央 2021-01-21 00:14

Hullo everyone,

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\" t

1条回答
  •  [愿得一人]
    2021-01-21 01:00

    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.

    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.

    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:

    • 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].

    0 讨论(0)
提交回复
热议问题