【问题标题】:GraphQL relationship returning nullGraphQL 关系返回 null
【发布时间】:2019-07-11 23:40:18
【问题描述】:

我正在学习 graphql 并使用 mongodb 数据库开发一个简单的 API。我无法弄清楚为什么在我的架构中声明的关系不起作用:

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
      }
]

知道我在这里缺少什么吗?

【问题讨论】:

标签: node.js mongodb graphql


【解决方案1】:

问题在于您的解决方案:

根据您链接的存储库,您的查询如下所示:

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

module.exports = queries;

People 架构如下所示:

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

您在 People 中实现的 GraphQL 关系有一个 Service Type,而您从数据库返回时只有服务 _id

您有 2 个解决方案:

A) 您还想在查询 People 时检索 Service 对象。在这种情况下,您需要使用猫鼬populate 函数: People: () => People.find({}).populate('service'),

上面将为 People 提供引用的 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) 解决方案,但我仍然得到位置字段的空结果。并出现以下错误:``错误:无法为不可为空的字段 Service.location 返回 null。 ``
  • 这可能是因为您的服务类型中有id: ID!,而我猜_id 是从数据库返回的。我猜您也不想对字段 id 使用类型解析器选项,我正在编辑我的答案以修复该错误
  • 再次感谢。我是 node.js、graphql 和 mongodb 的新手,所以我可能没有正确实施您的解决方案,因为我仍然得到 null 结果。您介意在我的仓库中创建一个拉取请求吗?
  • 请先将 package.json 添加到您的仓库中。
  • 更深入地查看您的代码恐怕您可能不会存储数据,因为它应该放在首位。您可以将来自您的数据库的实际示例对象添加到您的存储库中,用于一个人员和相关服务吗?
猜你喜欢
  • 2020-09-09
  • 2020-03-07
  • 2019-03-08
  • 2020-04-05
  • 2020-12-24
  • 2014-08-21
  • 2019-05-17
相关资源
最近更新 更多