Связь GraphQL возвращает значение null

Я изучаю graphql и работаю над простым API с базой данных mongodb. Я не могу понять, почему отношения, объявленные в моей схеме, не работают:

type People {
    id:ID!
    firstName:String!
    lastName:String!
    email:String!
    serviceId:String
    apps:[String]
    service:Service
}
type Service {
    id:ID!
    name:String!
    location:String!
    peoples:[People]
}

Когда я запускаю этот запрос:

query getLocationByPerson {
   People {
      firstName
      lastName
      service {
        location
      }
   }
}

Вот что я получаю:

"People": [
      {
        "firstName": "John",
        "lastName": "DOE",
        "service": null
      },
      {
        "firstName": "Jane",
        "lastName": "DOE",
        "service": null
      }
]

Есть идеи, что мне здесь не хватает?

Как выглядит ваш резольвер?

Michael 18.02.2019 16:37

весь код здесь: github.com/fabricezerrouki/graphql-игровая площадка спасибо

user3414794 18.02.2019 16:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
1 264
1

Ответы 1

Проблема заключается в ваших решателях:

На основе репо, которое вы связали, ваши запросы выглядят следующим образом:

const People = require('../database/people');
const Service = require('../database/service');
const queries = {
    People: () => People.find({}),
    ...
    Service: () => Service.find({}),
    ...
  };

module.exports = queries;

Схема Люди выглядит следующим образом:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;
const peopleSchema = new Schema({
    Xid: { type: String },
    firstName: { type: String },
    lastName: { type: String },
    email: { type: String },
    apps: { type: Array },
    serviceId: { type: String },
    service: { type: Schema.Types.ObjectId, ref: 'service' }
},{ versionKey: false })

module.exports = mongoose.model('people', peopleSchema);

People.find() вернет только службу _id, но не весь объект службы. Вот почему вы получаете null в ответ.

Отношения GraphQL, которые вы реализовали в People, имеют Service Type, в то время как вы получаете из базы данных только сервис _id.

У вас есть 2 решения:

A) Вы также хотите получить объект службы при запросе людей. В этом случае вам нужно использовать функцию мангуста populate: People: () => People.find({}).populate('service'),

Вышеприведенное предоставит людям указанный объект службы (а не только _id)

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

People: async () => {
      const people = await People.find({}).populate('service').exec()
      return people.map(person => ({
        ...person._doc,
        id: person._doc._id,
        service: {
          ...person._doc.service._doc,
          id: person._doc.service._doc._id,
        },
      }))
    }, return people
}

Вышеизложенное весьма запутанно. Я настоятельно рекомендую использовать решение (B)

Документы о populate(): https://mongoosejs.com/docs/populate.html

B) Используйте преобразователь type

// Type.js
const Service = require('../database/service');
const types = {
    People: {
      // you're basically saying: In People get service field and return...
      service: ({ service }) => Service.findById(service), // service in the deconstructed params is just an id coming from the db. This param comes from the `parent` that is People
    },
   Service: {
     id: ({_id}) => _id, // because you're using id in your schema
},
  };

module.exports = queries;

Примечание по реализации этой опции:

  • это мой предпочтительный вариант, хотя в конечном итоге вам понадобится загрузчик данных для пакетных вызовов базы данных, иначе это будет очень неэффективно. В основном вам нужно решить проблему N + 1 и обеспечить эффективность запросов к вашей базе данных. Вот тут есть очень хорошая статья про это: http://www.petecorey.com/blog/2017/08/14/batching-graphql-queries-with-dataloader/?from=east5th.co

Спасибо за вашу помощь. Я попробовал решение A), но я все еще получаю нулевой результат для поля местоположения. И следующая ошибка: «Ошибка: невозможно вернуть значение NULL для ненулевого поля Service.location. ``

user3414794 19.02.2019 10:59

Вероятно, это потому, что у вас есть id: ID! в вашем типе Сервиса, а _id, я думаю, возвращается из БД. Поскольку я предполагаю, что вы не хотите использовать параметр распознавателя типов для поля id, я также редактирую свой ответ, чтобы исправить эту ошибку.

Ric0 19.02.2019 11:47

Еще раз спасибо. Я новичок в node.js, graphql и mongodb, поэтому, вероятно, я неправильно реализую ваши решения, потому что все равно получаю нулевой результат. Не могли бы вы создать запрос на включение в моем репо, пожалуйста?

user3414794 19.02.2019 14:13

Сначала добавьте package.json в свой репозиторий.

Ric0 19.02.2019 14:14

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

Ric0 19.02.2019 15:25

Я загрузил скриншот как сервисов, так и коллекций людей.

user3414794 19.02.2019 15:43

Вижу в peoples-collection.png что есть serviceId String, но должно быть и service ObjectId

Ric0 19.02.2019 19:03

Большое спасибо Ric0, я обновил все по вашему совету, но теперь я получаю другую ошибку: `` TypeError: Cannot read property '_id' of undefined в People.people.map.person (graphql-mongo\resolvers\Query .js:11:40) ``

user3414794 20.02.2019 10:20

Я обновил репозиторий последними изменениями, которые я сделал благодаря вам, но все еще не работает :(

user3414794 26.02.2019 10:35
People: { Service: ({ serviceId }) => Service.findById(serviceId) },
Ric0 27.02.2019 09:50

Другие вопросы по теме