Apollo graphql 正在为 mongodb 中的空子文档返回空数据
Posted
技术标签:
【中文标题】Apollo graphql 正在为 mongodb 中的空子文档返回空数据【英文标题】:Apollo graphql is returning null data for an empty subdocument in mongodb 【发布时间】:2019-10-15 10:33:43 【问题描述】:我在我的 apollo 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 个具有空值的项目。 订阅返回正确,但它几乎与联系人字段相同,只是在 mongoose 模型中是“课程”类型而不是“用户”类型。
【问题讨论】:
【参考方案1】:我怀疑有人会遇到这种类型的错误,但如果您遇到这种情况,这里有一个解决方案。在开发过程中,我将此代码放在解析器中以进行测试。删除它解决了这个问题。
// USER RESOLVER
...
Query: ...,
/* code to remove
User:
contacts: user =>
return ["Mo", "Larry", "Curly"]
*/
Mutation: ...
一件非常微不足道的事情,但几个月没有出现在这个实际代码中,所以很难发现。我从没想过这三个臭皮囊会让我这么头疼。
【讨论】:
以上是关于Apollo graphql 正在为 mongodb 中的空子文档返回空数据的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Redux 应用程序转换为 GraphQL/Apollo?
Apollo GraphQL:为 HTTPBatchedNetworkInterface 设置端口?
使用 graphql 和 apollo 客户端刷新 Angular 令牌