【问题标题】:Handling Mongoose Populated Fields in GraphQL在 GraphQL 中处理 Mongoose 填充字段
【发布时间】:2017-05-15 22:07:13
【问题描述】:

如何表示可以是简单的ObjectId 字符串或填充的对象实体的字段?

我有一个表示“设备类型”的 Mongoose 架构,如下所示

// assetSchema.js

import * as mongoose from 'mongoose'
const Schema = mongoose.Schema;

var Asset = new Schema({  name : String,
                          linked_device: { type: Schema.Types.ObjectId, 
                                           ref: 'Asset'})

export AssetSchema = mongoose.model('Asset', Asset);

我试图将其建模为 GraphQLObjectType,但我对如何允许 linked_ue 字段采用两种类型的值感到困惑,一种是 ObjectId,另一种是完整的 Asset 对象(当它已填充)

// graphql-asset-type.js

import { GraphQLObjectType, GraphQLString } from 'graphql'

export var GQAssetType = new GraphQLObjectType({
           name: 'Asset',
           fields: () => ({
               name: GraphQLString,
               linked_device: ____________    // stumped by this
});

我已经研究过联合类型,但问题是联合类型需要将字段规定为其定义的一部分,而在上述情况下,linked_device 字段下方没有字段linked_device对应一个简单的ObjectId

有什么想法吗?

【问题讨论】:

    标签: node.js mongodb mongoose graphql graphql-js


    【解决方案1】:

    当我遇到这篇文章时,我正试图解决提取关系数据的一般问题。需要明确的是,最初的问题似乎是当字段可能包含 ObjectId 或 Object 时如何动态解析数据,但是我不认为首先让字段存储对象或 objectId 是好的设计。因此,我有兴趣解决将字段分开的简化场景——一个用于 Id,另一个用于对象。我也认为使用工会过于复杂,除非您实际上有其他场景,例如上面引用的文档中描述的场景。我认为下面的解决方案可能会让其他人感兴趣......

    注意:我使用的是 graphql-tools,所以我的类型是编写的模式语言语法。因此,如果您的用户类型具有这样的字段:

    type User {
        _id: ID
        firstName: String
        lastName: String
        companyId: ID
        company: Company
    }
    

    然后在我的用户解析器函数代码中,我添加了这个:

      User: {   // <-- this refers to the User Type in Graphql
        company(u) {   // <-- this refers to the company field
          return User.findOne({ _id: u.companyId }); // <-- mongoose User type
        },
      }
    

    以上内容与已有的用户解析器功能一起使用,并允许您编写如下 GQL 查询:

    query getUserById($_id:ID!) 
        { getUserById(_id:$_id) {
        _id
        firstName
        lastName
        company {
            name
        }
        companyId
        }}
    

    问候,

    S。阿罗拉

    【讨论】:

    • 这看起来不像是这个问题的答案。如果您对不同的问题有答案,请尝试找到一个实际提出您要回答的问题的问题,然后在此处发布您的答案。如果不存在这样的问题,如果您认为这是一个有用的问题,您可以自己发布一个。请注意,所有答案都必须是尝试回答最上面的问题,而不仅仅是一些相关问题。
    • 它试图回答可能存在的潜在挑战......问题被提出并按要求回答......但我试图重新构建正确的问题是什么,并质疑前提。让字段存储 object 或 objectId 并不是一个好的设计,所以我建议有一个更好的方法和一个更简单的答案。只是一个想法。
    • 嗯,好的。您可能希望在答案本身中更清楚地说明这一点。
    • 已澄清。感谢您的反馈。点赞赞赏!
    • 感谢您的澄清。不幸的是,我不适合对这篇文章进行投票,因为我没有领域知识,因此无法真正判断内容。
    【解决方案2】:

    事实上,linked_device 字段可以使用unioninterface 类型。

    使用联合类型,可以实现GQAssetType如下:

    // graphql-asset-type.js
    
    import { GraphQLObjectType, GraphQLString, GraphQLUnionType } from 'graphql'
    
    var LinkedDeviceType = new GraphQLUnionType({
      name: 'Linked Device',
      types: [ ObjectIdType, GQAssetType ],
      resolveType(value) {
        if (value instanceof ObjectId) {
          return ObjectIdType;
        }
        if (value instanceof Asset) {
          return GQAssetType;
        }
      }
    });
    
    export var GQAssetType = new GraphQLObjectType({
      name: 'Asset',
      fields: () => ({
        name: { type: GraphQLString },
        linked_device: { type: LinkedDeviceType },
      })
    });
    

    看看这个出色的article on GraphQL union and interface

    【讨论】:

    • 感谢@AhmadFerdous 的帮助。一个问题,在value instanceof Objectid 行中,ObjectId 是什么?是var ObjectId = mongoose.Schema.Types.ObjectId 吗?还有ObjectIdType 是什么样子的?
    • 是的,它是猫鼬 ObjectId。 ObjectIdType 只是一个包装 GraphQL 对象类型,它可以有一个字符串字段作为 id。
    • 感谢@AhmadFerdous,这真的很有帮助。我还在这里问了另一个问题,您可能可以提供帮助,非常感谢您的支持:stackoverflow.com/questions/41427320/…
    • 不确定 ObjectIdType 来自哪里......它的新 ObjectId?你能提供完整的工作示例吗?
    猜你喜欢
    • 2012-01-22
    • 2017-05-21
    • 2013-07-06
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 2021-04-19
    • 2015-09-19
    相关资源
    最近更新 更多