Использовать результат запроса в качестве аргумента на следующем уровне в GraphQL - PullRequest
0 голосов
/ 15 января 2019

Привет всем,

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

Я хотел бы использовать результат запроса в качестве аргумента для другого вложенного запроса.

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?

Спасибо за любую помощь!

1 Ответ

0 голосов
/ 15 января 2019

Единственным способом замены значений в документе GraphQL являются переменные, которые должны быть объявлены в определении вашей операции, а затем включены вместе с вашим документом как часть вашего запроса. Не существует встроенного способа ссылки на ранее разрешенные значения в том же документе.

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

Например, как минимум, вы можете полностью исключить аргумент studentId для assessmentInfoByStudentId. coursesByStudentCourseStudentIdAndCourseId - это поле на узле учащегося, поэтому его распознаватель уже может получить доступ к идентификатору учащегося. Он может передавать эту информацию каждому узлу курса, который затем может использоваться assessmentInfoByStudentId.

Тем не менее, вам, вероятно, лучше полностью переосмыслить, как вы настроили свои соединения. Я не знаю, как выглядит ваш базовый уровень хранения, или как клиенту нужны данные, поэтому сложно дать какие-то конкретные рекомендации. Однако, для примера, давайте предположим, что у нас есть три типа - Course, Student и AssessmentInfo. A Course имеет множество Students, Student имеет множество Courses, а AssessmentInfo имеет один Student и один Course.

Мы можем представить все три объекта как запросы корневого уровня:

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

Каждый узел может иметь соединение с двумя другими типами:

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

  }
}

Если мы хотим выбрать всех студентов, и чтобы каждый студент знал, какие курсы он / она посещает, и его / ее средневзвешенную оценку за этот курс, мы можем тогда написать запрос:

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

  }
}

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

  • Добавьте аргументы фильтра в поля подключения вместо создания отдельных полей для каждого сценария, который необходимо охватить. Одно поле courses для типа Student может иметь различные аргументы, например semester, campus или isPassing - это чище и гибче, чем создание различных полей, таких как coursesBySemester, coursesByCampus и т. д.
  • Если вы имеете дело с агрегированными значениями, такими как среднее, минимальное, максимальное и т. Д., Может иметь смысл выставить эти значения в качестве полей для каждого типа подключения, точно так же, как поле count иногда доступно рядом с nodes поле. Есть (предложение) [https://github.com/prisma/prisma/issues/1312] для Prisma, которое иллюстрирует один довольно аккуратный способ обработки этих агрегированных значений. Выполнение чего-либо подобного будет означать, что если у вас уже есть, например, тип Assessment, поля подключения может быть достаточно для предоставления агрегированных данных об этом типе (например, средние оценки) без необходимости предоставления отдельного типа AssessmentInfo.
  • Фильтрация относительно проста, группировка немного сложнее. Если вы обнаружите, что вам нужны узлы соединения, сгруппированные по определенному полю, опять же, это лучше всего сделать, выставив дополнительное поле на самом соединении (как это делает Гэтсби) [https://www.gatsbyjs.org/docs/graphql-reference/#group].
...