使用 graph-gophers/graphql-go 包的 graphql 突变查询错误
graphql mutation query error using graph-gophers/graphql-go package
问题
下面的突变
mutation {
signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
email
username
}
}
错误如下
{
"errors": [
{
"message": "Cannot query field \"email\" on type \"SignUpResponse\".",
"locations": [
{
"line": 3,
"column": 5
}
]
},
{
"message": "Cannot query field \"username\" on type \"SignUpResponse\".",
"locations": [
{
"line": 4,
"column": 5
}
]
}
]
}
预期
{
"data": {
"signUp": {
"email": "newuser@gmail.com",
"username": "newUser"
}
}
}
代码片段
schema.graphql
片段
...
input SignUpInput {
username: String!
email: String!
password: String!
}
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
resolvers.go
片段
...
// UserResolver ingests properties from User
type UserResolver struct{ u *User }
// UserID returns the userId of the user
func (r *UserResolver) UserID() graphql.ID {
return r.u.UserID
}
// Username returns the username of the user
func (r *UserResolver) Username() string {
return r.u.Username
}
// Email returns the email of the user
func (r *UserResolver) Email() string {
return r.u.Email
}
// Password returns the password of the user
func (r *UserResolver) Password() string {
return r.u.Password
}
type SignUpArgs struct {
Username string
Email string
Password string
}
// SignUp returns a new User from Db and its responses
func (r *RootResolver) SignUp(args struct{ SignUpInput *SignUpArgs }) (*SignUpResolver, error) {
// Find user:
u, err := r.Db.CreateUser(args.SignUpInput)
// need to deal with this different, so sort of error if we can't create the user
// a. user already exists
// b. email already exists
if err != nil {
// error creating the user
msg := "already signed up"
return &SignUpResolver{
Status: false,
Msg: &msg,
User: nil,
}, err
}
return &SignUpResolver{
Status: true,
Msg: nil,
User: &UserResolver{&u},
}, nil
}
// SignUpResolver is the response type
type SignUpResolver struct {
Status bool
Msg *string
User *UserResolver
}
// Ok for SignUpResponse
func (r *SignUpResolver) Ok() bool {
return r.Status
}
// Error for SignUpResponse
func (r *SignUpResolver) Error() *string {
return r.Msg
}
// AddedUser for SignUpResponse
func (r *SignUpResolver) AddedUser() *UserResolver {
return r.User
}
postgres.go - 数据库操作
// User returns a single user
func (d *Db) User(uid graphql.ID) (User, error) {
var (
sqlStatement = `SELECT * FROM users WHERE user_id=;`
row *sql.Row
err error
u User
)
row = d.QueryRow(sqlStatement, uid)
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan")
return u, nil
}
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES (, , )
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
u, _ = d.User(userID)
return u, nil
}
我已经尝试将 CreateUser
更改为此
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES (, , )
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan User")
return u, nil
}
显然没有做到。因此问题是,为什么查询错误?似乎 UserResolver
不能 return User
数据,前提是该行是从数据库 return 编辑的。
您的类型定义包括:
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
您似乎正在尝试查询 returned User
的字段,但 signUp
没有 return 一个 User
对象。相反,signUp
return 是一个 SignUpResponse
对象,如错误所述,该对象没有任何名为 email
或 username
.
的字段
正确的查询应该是这样的:
mutation {
signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
addedUser {
email
username
}
ok
error
}
}
问题
下面的突变
mutation {
signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
email
username
}
}
错误如下
{
"errors": [
{
"message": "Cannot query field \"email\" on type \"SignUpResponse\".",
"locations": [
{
"line": 3,
"column": 5
}
]
},
{
"message": "Cannot query field \"username\" on type \"SignUpResponse\".",
"locations": [
{
"line": 4,
"column": 5
}
]
}
]
}
预期
{
"data": {
"signUp": {
"email": "newuser@gmail.com",
"username": "newUser"
}
}
}
代码片段
schema.graphql
片段
...
input SignUpInput {
username: String!
email: String!
password: String!
}
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
resolvers.go
片段
...
// UserResolver ingests properties from User
type UserResolver struct{ u *User }
// UserID returns the userId of the user
func (r *UserResolver) UserID() graphql.ID {
return r.u.UserID
}
// Username returns the username of the user
func (r *UserResolver) Username() string {
return r.u.Username
}
// Email returns the email of the user
func (r *UserResolver) Email() string {
return r.u.Email
}
// Password returns the password of the user
func (r *UserResolver) Password() string {
return r.u.Password
}
type SignUpArgs struct {
Username string
Email string
Password string
}
// SignUp returns a new User from Db and its responses
func (r *RootResolver) SignUp(args struct{ SignUpInput *SignUpArgs }) (*SignUpResolver, error) {
// Find user:
u, err := r.Db.CreateUser(args.SignUpInput)
// need to deal with this different, so sort of error if we can't create the user
// a. user already exists
// b. email already exists
if err != nil {
// error creating the user
msg := "already signed up"
return &SignUpResolver{
Status: false,
Msg: &msg,
User: nil,
}, err
}
return &SignUpResolver{
Status: true,
Msg: nil,
User: &UserResolver{&u},
}, nil
}
// SignUpResolver is the response type
type SignUpResolver struct {
Status bool
Msg *string
User *UserResolver
}
// Ok for SignUpResponse
func (r *SignUpResolver) Ok() bool {
return r.Status
}
// Error for SignUpResponse
func (r *SignUpResolver) Error() *string {
return r.Msg
}
// AddedUser for SignUpResponse
func (r *SignUpResolver) AddedUser() *UserResolver {
return r.User
}
postgres.go - 数据库操作
// User returns a single user
func (d *Db) User(uid graphql.ID) (User, error) {
var (
sqlStatement = `SELECT * FROM users WHERE user_id=;`
row *sql.Row
err error
u User
)
row = d.QueryRow(sqlStatement, uid)
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan")
return u, nil
}
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES (, , )
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
u, _ = d.User(userID)
return u, nil
}
我已经尝试将 CreateUser
更改为此
// CreateUser - inserts a new user
func (d *Db) CreateUser(i *SignUpArgs) (User, error) {
var (
sqlStatement = `
INSERT INTO users (email, username, password)
VALUES (, , )
RETURNING user_id`
userID graphql.ID
row *sql.Row
err error
u User
)
/***************************************************************************
* retrieve the UserID of the newly inserted record
* db.Exec() requires the Result interface with the
LastInsertId() method which relies on a returned value from postgresQL
* lib/pq does not however return the last inserted record
****************************************************************************/
row = d.QueryRow(sqlStatement, i.Email, i.Username, i.Password)
if err = row.Scan(&userID); err != nil {
// err: username or email is not unqiue --> user already exsits
return u, err
}
err = row.Scan(
&u.UserID,
&u.Username,
&u.Email,
&u.Password,
)
util.Check(err, "row.Scan User")
return u, nil
}
显然没有做到。因此问题是,为什么查询错误?似乎 UserResolver
不能 return User
数据,前提是该行是从数据库 return 编辑的。
您的类型定义包括:
type Mutation {
signUp(signUpInput: SignUpInput): SignUpResponse!
}
type SignUpResponse {
ok: Boolean!
error: String
addedUser: User
}
您似乎正在尝试查询 returned User
的字段,但 signUp
没有 return 一个 User
对象。相反,signUp
return 是一个 SignUpResponse
对象,如错误所述,该对象没有任何名为 email
或 username
.
正确的查询应该是这样的:
mutation {
signUp(signUpInput: {email: "newuser@gmail.com", username: "newUser", password: "asdfasdfawerawer"}) {
addedUser {
email
username
}
ok
error
}
}