在猫鼬和GraphQL中用于ObjectId字段的正确类型是什么?

时间:2018-09-09 10:06:47

标签: node.js mongodb mongoose graphql

this tutorial之后,我有一个猫鼬模型:(我使用的是“帐户”一词,而不是“ Todo”,但这是一回事)

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中可以看到它:

From MongoDB Compass showing created object

但是读取值似乎有问题。

GraphQLIDmongoose.Schema.Types.ObjectId的兼容性如何?如果它们不兼容,我会误解该教程,尤其是它的使用:

newAccount.id = newAccount._id;

?我无法确定是GraphQL,MongoDB,Mongoose还是其他东西抛出了错误。

编辑

有关错误的任何信息

  

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

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

编辑2

这是由a change对最近引入的graphql软件包造成的,并且有a PR个正在等待合并的文件将其解决。

3 个答案:

答案 0 :(得分:3)

我没有发现问题,而是使用我现有的代码库之一运行了此代码。除了我将突变包装在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回购。在此存储库中,该应用使用v0.13.2,而您正在使用通过v14.0.2安装的npm i graphql。将graphql降级为v0.13.2

答案 1 :(得分:1)

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

为了解决此问题,请为每个获取的数据调用toJson函数,或仅添加一个虚拟id,如下所示:

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

答案 2 :(得分:0)

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

换句话说,代替这个

ObjectID

这样做

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