GraphQL Mongoose:转换为 ObjectId 的值失败

Posted

技术标签:

【中文标题】GraphQL Mongoose:转换为 ObjectId 的值失败【英文标题】:GraphQL Mongoose: Cast to ObjectId failed for value 【发布时间】: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 中,但没有任何帮助。我在这里错过了什么?

【问题讨论】:

【参考方案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 ) => 使用解构赋值

以上是关于GraphQL Mongoose:转换为 ObjectId 的值失败的主要内容,如果未能解决你的问题,请参考以下文章

从带有子字段的猫鼬模式生成 Graphql 类型

如何将 Mongoose 与 GraphQL 和 DataLoader 一起使用?

GraphQL & Mongoose Schema - 如何将一组 mongoose objectId 引用存储到另一种类型?

如何使用 graphql 和 mongoose 进行突变

NestJS + Mongoose + GraphQL:“填充”不起作用

如何在不创建 Mongoose 模型的情况下将 GraphQL 与 Mongoose 和 MongoDB 一起使用