Apollo graphql在mongodb中返回空子文档的空数据

时间:2019-05-29 18:56:58

标签: reactjs mongodb mongoose apollo apollo-client

我向我的阿波罗graphql突变添加了另一个字段(联系人),但是在检索该字段时会产生错误的数据。即使匹配的mongodb字段是否包含真实数据,graphql也会返回具有空值的多字段。

我已经尝试在apollo客户端graphql选项中删除__typename,但这无济于事。当前堆栈为:

reactjs 16.8.5
react-apollo 2.5.2
mongodb 3.6.11
mongoose 5.3.6
apollo-server 2.3.1 

我不明白为什么要这样做,因为我有另一个几乎相同但可以正确返回的子文档。

// CLIENTSIDE
// APOLLO SETUP
const cache = new InMemoryCache({
   dataIdFromObject: object => object.key || null
 })

 const AuthLink = (operation, forward) => {
   const token = cookies._uid
   operation.setContext(context => ({
     ...context,
     headers: {
       ...context.headers,
       authorization: token
     }
   }))

   return forward(operation)
 }

 const httpLink = new HttpLink({
   uri:"/graphql",
   credentials: "include"
 })

// mutation
 export const LOGIN_MUTATION = gql`
  mutation loginMutation($email: String!, $password: String!) {
    login(input: {email: $email, password: $password}) {
      token
      user {
        _id
        contacts {  // This is the subfield in question
          _id
          username
        }
        subscriptions {  // This subfield returns corretly
          _id
          title
          levels {
            _id
          }
        }
      }
      error {
        path
        message
      }
    }
  }
`

// SERVERSIDE
// APOLLO SETUP
 const baseSchema = `
   schema {
     query: Query,
     mutation: Mutation
   }
 `
 const schema = makeExecutableSchema({
   typeDefs: [
     userTypeDefs,
   ],
   resolvers: merge(
     {},
     userResolvers,
   )
 })

 const {ObjectId} = mongoose.Types
 ObjectId.prototype.valueOf = function() {
  return this.toString()
 }

 export default new ApolloServer({
   introspection: true,
   credentials: true,
   schema,
   context: ({req, res}) => ({
     url: req.protocol + "://" + req.get("host"), 
     req
   })
 })

// USER MONGOOSE MODEL
 export const UserSchema = new mongoose.Schema(
   {
     contacts: [
       {
         type: mongoose.Schema.Types.ObjectId,
         ref: "User"
       }
     ],     
     firstName: {
       type: String
     },     
     lastName: {
       type: String
     },     
     username: {
       type: String,
       lowercase: true,
       unique: true,
       required: [true, "can't be blank"],
       match: [/^[a-zA-Z0-9]+$/, "is invalid"],
       index: true
     },

     sentRequests: [
       {
         username: {
           type: String,
           default: ""
         }
       }
     ],     
     subscriptions: [
       {
         type: mongoose.Schema.Types.ObjectId,
         ref: "Course"
       }
     ],
     password: {
       default: "",
       required: [true, "can't be blank"],
       type: String
     }
   },
   {timestamps: true}
 )

 UserSchema.plugin(uniqueValidator, {message: "is already taken."})
 export default mongoose.model("User", UserSchema)

// USER GRAPHQL SCHEMA
type User {
   _id: ID
   contacts: [User]
   email: String!
   username: String
   subscriptions: [Course]
   createdAt: String
   updatedAt: String
 }

 type AuthPayload {
   token: String
   user: User
   error: [Error]
 }

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

 type Mutation {
   login(input: LoginInput): AuthPayload
 }

// USER RESOLVER
 const login = async (parent, args, ctx, info) => {   
   let email = args.email

   let user = await User.findOne({email})
     .populate("subscriptions")
     .populate("contacts")
     .exec()

  if (!user) {
     arrayOfErrors.push({
       path: "email",
       message: "invalid email"
     })
   } else if (user) {

   console.log("user: ", user)


   return {
     user,
     error: arrayOfErrors
   }
 }

 Mutation: {
   login
 }
// CONSOLE LOG CLIENTSIDE
user:
  confirmed: true
  contacts: Array(3)  // returns an array of 3 items??  It's [] in mongodb
    0: {_id: null, username: null}
    1: {_id: null, username: null}
    2: {_id: null, username: null}
    length: 3
    __proto__: Array(0)
  subscriptions: Array(1)
    0: {_id: "5cd36fc1c8d1e222b99d9c58", title: "Korean Class 101 Study", 
    length: 1
    __proto__: Object
__proto__: Object

// CONSOLE LOG SERVERSIDE
POST /graphql 200 64.359 ms - -
user: {
  contacts: [ ],
  subscriptions:
   [ { _id: 5cd6f7f8212af32c75555d4b,
       subscribers: 2,
       owner: 5cd36edec8d1e222b99d9c57,
       createdAt: 2019-05-09T00:09:37.845Z,
       updatedAt: 2019-05-11T16:36:14.661Z,
       __v: 23 } ],
  password: '$2b$10$bkjiazklcoqlkJSJSAioxoAqkoajsdjnqjkiaallaadfadfp7zS',
  _id: 5cd36edec8d1e222b99d9c57,
  email: 'example@test.com',
  username: 'example',
  createdAt: 2019-05-09T00:05:50.314Z,
  updatedAt: 2019-05-29T17:23:21.545Z,
  __v: 32
}

我希望有一个空数组返回[],而不是graphql返回3个项目的数组,这些数组具有空值。即使我将真实联系人添加到数据库中,它仍然会返回3个带有空值的项目。 订阅已正确返回,但与猫鼬字段中的联系人字段几乎相同,只是猫鼬模型中的类型为“课程”,而不是“用户”类型。

1 个答案:

答案 0 :(得分:0)

我怀疑有人会遇到这种类型的错误,但是如果您这样做,这就是解决方案。在开发期间,出于测试目的,我已将此代码放置在解析器中。删除它可以解决问题。

// USER RESOLVER
...
Query: {...},

/* code to remove
User: {
  contacts: user => {
    return ["Mo", "Larry", "Curly"]
  }
}
*/ 

Mutation: {...}

一件非常琐碎的事,但是几个月没去看这个实际代码,很难发现。我从没想过这3种臭虫会给我带来如此多的头痛。