Я изучаю 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
}
]
Есть идеи, что мне здесь не хватает?
весь код здесь: github.com/fabricezerrouki/graphql-игровая площадка спасибо





Проблема заключается в ваших решателях:
На основе репо, которое вы связали, ваши запросы выглядят следующим образом:
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;
Примечание по реализации этой опции:
Спасибо за вашу помощь. Я попробовал решение A), но я все еще получаю нулевой результат для поля местоположения. И следующая ошибка: «Ошибка: невозможно вернуть значение NULL для ненулевого поля Service.location. ``
Вероятно, это потому, что у вас есть id: ID! в вашем типе Сервиса, а _id, я думаю, возвращается из БД. Поскольку я предполагаю, что вы не хотите использовать параметр распознавателя типов для поля id, я также редактирую свой ответ, чтобы исправить эту ошибку.
Еще раз спасибо. Я новичок в node.js, graphql и mongodb, поэтому, вероятно, я неправильно реализую ваши решения, потому что все равно получаю нулевой результат. Не могли бы вы создать запрос на включение в моем репо, пожалуйста?
Сначала добавьте package.json в свой репозиторий.
Глядя более глубоко в ваш код, я боюсь, что вы не можете хранить данные так, как это должно быть в первую очередь. Можете ли вы добавить в свое репо фактический образец объекта, поступающий из вашей базы данных как для одного человека, так и для связанной с ним службы?
Я загрузил скриншот как сервисов, так и коллекций людей.
Вижу в peoples-collection.png что есть serviceId String, но должно быть и service ObjectId
Большое спасибо Ric0, я обновил все по вашему совету, но теперь я получаю другую ошибку: `` TypeError: Cannot read property '_id' of undefined в People.people.map.person (graphql-mongo\resolvers\Query .js:11:40) ``
Я обновил репозиторий последними изменениями, которые я сделал благодаря вам, но все еще не работает :(
People: { Service: ({ serviceId }) => Service.findById(serviceId) },
Как выглядит ваш резольвер?