【问题标题】:GraphQL Mongoose: Cast to ObjectId failed for valueGraphQL Mongoose:转换为 ObjectId 的值失败
【发布时间】:2021-03-09 12:49:22
【问题描述】:

我有以下 GraphQL 解析器:

const Post = require("../../models/Post");

module.exports = {
  getAllActivePosts: async (userId) => {
    try {
      const posts = await Post.find({
        userId: userId
      })
        .select(["name", "createdAt"])
        .populate("posts", ["name", "createdAt"]);

      return posts;
    } catch (err) {
      console.log(err);
      throw err;
    }
  },
};

它试图通过 Post 模型中的用户 ID 获取所有活跃的帖子:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const PostSchema = new mongoose.Schema({
  userId: {
    type: Schema.Types.ObjectId,
    ref: "User",
    required: true,
  },
  content: {
    type: String,
    required: true,
  },
  createdAt: {
    type: Date,
    required: true,
  }
});

module.exports = Post = mongoose.model("Post", PostSchema);

这是 GraphQL 架构:

const { buildSchema } = require('graphql');

module.exports = buildSchema(`
        type User {
            _id: MongoId!
            email: String!
            password: String
        }

        type Post {
            _id: MongoId!
            userId: MongoId!
            content: String!
            createdAt: String!
        }

        scalar MongoId

        input LoginInput {
            email: String!
            password: String!
        }

        type RootQuery {
            login(email: String!, password: String!): AuthData!
            getAllActivePosts(userId: MongoId!): [Post]
        }

        type RootMutation {
            createUser(loginInput: LoginInput): AuthData!
        }

        schema {
            query: RootQuery
            mutation: RootMutation
        }
    `);

...以及我在 GraphiQL 中运行的 GraphQL 查询:

{
  getAllActivePosts(userId: "5fbfc92312b90071179a160f") {
    name
    createdAt
  }
}

为此,查询的结果是:

{
  "errors": [
    {
      "message": "Cast to ObjectId failed for value \"{ userId: '5fbfc92312b90071179a160f' }\" at path \"userId\" for model \"Post\"",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "getAllActivePosts"
      ]
    }
  ],
  "data": {
    "getAllActivePosts": null
  }
}

在此处搜索类似问题,尝试将 userId 包装在 ObjectId 中,但没有任何帮助。我在这里错过了什么?

【问题讨论】:

    标签: mongodb mongoose graphql


    【解决方案1】:

    一年前我曾遇到过一次这个问题,直到我得到了 graphql 的主要概念。 你在这里传递字符串

    {
      getAllActivePosts(userId: "5fbfc92312b90071179a160f") {
        name
        createdAt
      }
    }
    

    并且 graphql 期望有 mongoose.Types.ObjectId

    getAllActivePosts(userId: MongoId!): [Post]
    

    你需要做同步

     getAllActivePosts(userId: mongoose.Types.ObjectId("5fbfc92312b90071179a160f")) {
    

    但是使用上述方式,您没有资格在 graphiQL 中运行查询,因为没有定义猫鼬。

    type RootQuery {
        login(email: String!, password: String!): AuthData!
        getAllActivePosts(userId: String!): [Post]
    }
    

    更好的解决方案是使用 userId 输入作为字符串,然后在您的解析器函数上进行验证,例如

    getAllActivePosts: async ({ userId }) => {
        try {
          if(mongoose.Types.ObjectId.isValid(userId)) {
            const posts = await Post.find({
              userId: userId
            }) 
            .select(["name", "createdAt"])
            .populate("posts", ["name", "createdAt"]);
           // you can;t return null you need to return array
           return posts ? posts : []
          } else {
           // if mongoose id is wrong
           return []
          }
       } catch(error) {
        // it is better to throw error return blank array to complete flow
        throw error
       }
    }
    

    【讨论】:

    • 谢谢,我试过了,帖子里提到过。它没有帮助。
    • 您是否在查询getAllActivePosts(userId: String!): [Post] 中执行此操作,因为我有它的工作代码。谢谢
    • 谢谢,我找到了解决方案并在下面回答。谢谢你的字符串!
    【解决方案2】:

    原来,我直接使用userId,而我应该使用args.userId。下面的正确解析器:

    module.exports = {
      getAllActivePosts: async (args) => {
        try {
          const posts = await Post.find({
            userId: args.userId
          })
            .select(["name", "createdAt"])
            .populate("posts", ["name", "createdAt"]);
    
          return posts;
        } catch (err) {
          console.log(err);
          throw err;
        }
      },
    };
    

    对于架构:

    getAllActivePosts(userId: String!): [Post]
    

    【讨论】:

    • async ({ userId }) => { 使用解构赋值
    猜你喜欢
    • 2013-03-24
    • 2021-09-05
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 2021-03-14
    • 2020-04-18
    • 2020-12-16
    • 2022-08-15
    相关资源
    最近更新 更多