【问题标题】:What is the correct type to use for an ObjectId field across mongoose and GraphQL?跨 mongoose 和 GraphQL 的 ObjectId 字段使用的正确类型是什么?
【发布时间】:2019-02-14 00:57:04
【问题描述】:

this tutorial 之后,我有一个猫鼬模型:(我使用术语“帐户”而不是“待办事项”,但它是同一件事)

const Account = mongoose.model('Account', new mongoose.Schema({
  id: mongoose.Schema.Types.ObjectId,
  name: String
}));

还有一个 GraphQLObjectType:

const AccountType = new GraphQLObjectType({
  name: 'account',
  fields: function () {
    return {
      id: {
        type: GraphQLID
      },
      name: {
        type: GraphQLString
      }
    }
  }
});

和一个 GraphQL 突变来创建其中之一:

const mutationCreateType = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    add: {
      type: AccountType,
      description: 'Create new account',
      args: {
        name: {
          name: 'Account Name',
          type: new GraphQLNonNull(GraphQLString)
        }
      },
      resolve: (root, args) => {
        const newAccount = new Account({
          name: args.name
        });

        newAccount.id = newAccount._id;

        return new Promise((resolve, reject) => {
          newAccount.save(err => {
            if (err) reject(err);
            else resolve(newAccount);
          });
        });
      }
    }
  }
})

运行查询后:

mutation {
  add(name: "Potato")
  {
    id,
    name
  }
}

在 GraphiQL 中,我得到了响应:

{
  "errors": [
    {
      "message": "ID cannot represent value: { _bsontype: \"ObjectID\", id: <Buffer 5b 94 eb ca e7 4f 2d 06 43 a6 92 20> }",
      "locations": [
        {
          "line": 33,
          "column": 5
        }
      ],
      "path": [
        "add",
        "id"
      ]
    }
  ],
  "data": {
    "add": {
      "id": null,
      "name": "Potato"
    }
  }
}

对象创建成功,在MongoDB Compass中可以看到:

但读取值似乎有问题。

GraphQLIDmongoose.Schema.Types.ObjectId 的兼容性如何?如果它们不兼容,我是否误解了本教程,特别是它的用法:

newAccount.id = newAccount._id;

?我无法判断错误是由 GraphQL、MongoDB、Mongoose 还是其他东西引发的。

编辑

关于错误的任何信息

ID 不能代表值:{ _bsontype: \"ObjectID\", id: }

非常有帮助。我觉得它告诉我它无法序列化 BSON 对象.. 但随后它显示它已序列化。即使知道产生错误的技术(mongo?mongoose?graphql?)也会有所帮助。我在 Google 上没有运气。

编辑 2

这是最近引入的graphql包a change引起的,有a PR等待合并解决。

【问题讨论】:

    标签: node.js mongodb mongoose graphql


    【解决方案1】:

    我没有发现问题并使用我现有的代码库之一运行此代码。除了我将突变包装在 GraphQLObjectType 中。

    const Mutation = new GraphQLObjectType({
        name: 'Mutation',
        fields: {
            addAccount: {
                type: AccountType,
                description: 'Create new account',
                args: {
                    name: {
                        name: 'Account Name',
                        type: new GraphQLNonNull(GraphQLString)
                    }
                },
                resolve: (root, args) => {
                    const newAccount = new Account({
                        name: args.name
                    });
    
                    newAccount.id = newAccount._id;
    
                    return new Promise((resolve, reject) => {
                        newAccount.save(err => {
                            if (err) reject(err);
                            else resolve(newAccount);
                        });
                    });
                }
            }
        });
    

    要获得工作示例:Clone repo。在这个 repo 中,应用程序使用v0.13.2,而您使用的是通过npm i graphql 安装的v14.0.2。将graphql 降级为v0.13.2

    【讨论】:

    • 谢谢;我正在做同样的事情(不知道为什么会分裂)。我非常感谢您的工作示例,谢谢
    • 这些有点像 PITA 的错误...我想知道这是一个微妙的配置问题,还是与我正在使用的 node/mongo/mongoose/graphql/其他东西的版本相关的东西:(
    • @AlexMcMillan 我已经用回购链接编辑了我的答案。谢谢
    • 你的作品完美。我注意到您使用了 graphql v0.13.2 - 我使用的是 v14.0.2。将我的降级到相同的版本,问题就消失了。有趣,因为npm i graphql 安装了14.0.2。 (注意:我花了几个小时敲了敲脑袋才弄明白——谢谢你的例子!)
    • 如果您将此信息添加到您的答案中,我会勾选它;)感谢您的帮助!
    【解决方案2】:

    我使用了ID,效果很好!您的问题的原因不是 id 的类型!这是因为您为其提供了错误的值:ObjectID('actuall id')

    为了解决这个问题,为每个获取的数据调用toJson函数,或者像这样简单地添加一个虚拟id

    YourSchema.virtual('id').get(function() {
        return this.toJSON()._id
    }
    

    【讨论】:

      【解决方案3】:

      所以我刚刚发现_id 的类型为ObjectID,但似乎隐式转换为String。因此,如果您将 mongoose 模型 id 类型定义为 String 而不是 mongoose.Schema.Types.ObjectId 那么它应该可以工作。使用将 _id 复制到 id 的当前代码(来自 compose.com 教程),结果将是,在 Mongo 中(保存后),_id 将是 ObjectID 类型,而您的模型 id 将是字符串类型。

      换句话说,不是这个

      const Account = mongoose.model('Account', new mongoose.Schema({
        id: mongoose.Schema.Types.ObjectId,
        name: String
      }));
      

      这样做

      const Account = mongoose.model('Account', new mongoose.Schema({
        id: String,
        name: String
      }));
      

      【讨论】:

      • 想知道这种做法是否会影响 populate 在 mongoose 中的使用?
      猜你喜欢
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      • 2020-01-04
      • 1970-01-01
      • 2018-02-13
      • 2021-05-22
      • 1970-01-01
      • 2017-12-19
      相关资源
      最近更新 更多