Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I pass a customised parameter in query? #642

Closed
zhaoyi0113 opened this issue May 16, 2020 · 12 comments
Closed

How can I pass a customised parameter in query? #642

zhaoyi0113 opened this issue May 16, 2020 · 12 comments

Comments

@zhaoyi0113
Copy link

zhaoyi0113 commented May 16, 2020

I am using graphql_flutter in a flutter app. Below is my query code:

await this.gqClient.query(QueryOptions(documentNode: gql('''
    query posts(\$size: Int, \$lastEvaluatedKey: LastEvaluatedKey){
          posts(size: \$size, lastEvaluatedKey: \$lastEvaluatedKey) {
            posts {
              id
            }
            lastEvaluatedKey {
              id
              timestamp
            }
          }
        }
      '''),
       variables: {'size': this.pageSize, 'lastEvaluatedKey': this._lastEvaluatedKey}))

I got this error when executing above code:

OperationException (GraphQL Errors:
        Validation error of type UnknownType: Unknown type LastEvaluatedKey: Undefined location)

It seems that LastEvaluatedKey is not recognised. I have declared a dart class LastEvaluatedKey as below but it doesn't seem to help. Where should I put the LastEvaluatedKey definition in the client side?

class LastEvaluatedKey {
  final String id;
  final String timestamp;

  LastEvaluatedKey({this.id, this.timestamp});
}
@RanaOsamaAsif
Copy link

RanaOsamaAsif commented May 16, 2020

Hi, the solution is to create a toJson method in your LastEvaluatedKey class and return the fields of LastEvaluatedKey in the form of Map<String, dynamic>

@zhaoyi0113
Copy link
Author

zhaoyi0113 commented May 17, 2020

I have updated my class as below. But it is still not working. I still get the error OperationException (GraphQL Errors: Validation error of type UnknownType: Unknown type LastEvaluatedKey: Undefined location).

class LastEvaluatedKey {
  final String id;
  final int timestamp;

  LastEvaluatedKey({this.id, this.timestamp});

  Map<String, dynamic> toJson() {
    try {
      return {
        'id': this.id,
        'timestamp': this.timestamp,
      };
    } catch (err) {
      return null;
    }
  }
}

The query code is inside gql ''' ... '''. How does it make use of class in dart code?

When I debug above code, I can see the method toJson is called and the return value seems right

@micimize micimize mentioned this issue May 17, 2020
5 tasks
@micimize
Copy link
Collaborator

You currently have to call _lastEvaluatedKey.toJson() yourself, as as graphql doesn't currently do any serialization

If you're going to have a lot of input types that require serialization, you can us json.encode from dart:convert:

variables: json.encode(
  variables,
  toEncodable: (dynamic object) => object.toJson(),
)

@zhaoyi0113
Copy link
Author

Thanks for your feedback. But adding .toJson() doesn't seem to help.

await this.gqClient.query(QueryOptions(documentNode: gql('''
        query posts(\$size: Int, \$lastEvaluatedKey: LastEvaluatedKey){
          posts(size: \$size, lastEvaluatedKey: \$lastEvaluatedKey) {
            posts {
              id,
              message,
              photoPaths,
              userInfo {
                username,
                picture
              }
            }
            lastEvaluatedKey {
              id
              timestamp
            }
          }
        }
      '''), variables: {
                'size': this.pageSize,
                'lastEvaluatedKey': this._lastEvaluatedKey.toJson(),
              }));

I updated the code above but still get the same error:

OperationException (GraphQL Errors:
        Validation error of type UnknownType: Unknown type LastEvaluatedKey: Undefined location)

@micimize
Copy link
Collaborator

@zhaoyi0113 ohhh wait I think this error is that the graphql server doesn't recognize the type LastEvaluatedKey referenced in your query

@zhaoyi0113
Copy link
Author

I can send query from different client so I don't think it is an issue on the server side. However, I can make it work by extracting the query parameters from LastEvlauatedKey instance like below code:

await this.gqClient.query(QueryOptions(documentNode: gql('''
        query posts(\$size: Int, \$lastKeyId: String!, \$lastKeyTimestamp: Long){
          posts(size: \$size, lastEvaluatedKey: {id: \$lastKeyId, timestamp: \$lastKeyTimestamp}) {
            posts {
              id,
              message,
              photoPaths,
              userInfo {
                username,
                picture
              }
            }
            lastEvaluatedKey {
              id
              timestamp
            }
          }
        }
      '''), variables: {
                'size': this.pageSize,
                'lastKeyId': this._lastEvaluatedKey.id,
                'lastKeyTimestamp': this._lastEvaluatedKey.timestamp,
              }));

as you can see, it takes primitive types of parameters and set them in lastEvaluatedKey.
Would you consider to support passing object instance as the parameter in future release?

@micimize
Copy link
Collaborator

@zhaoyi0113 hmm, I'm fairly sure there must have been some difference. The error is a GraphQL validation error: Validation error of type UnknownType: Unknown type LastEvaluatedKey, and the only place it is referenced is

        query posts(\$size: Int, \$lastEvaluatedKey: LastEvaluatedKey){

If you want to investigate it further, come to the support channel in the discord

Would you consider to support passing object instance as the parameter in future release?
nested json Maps as variables should work just fine, but better support for .toJson implementing variables would be good, yes

@zhaoyi0113
Copy link
Author

zhaoyi0113 commented May 19, 2020

Where should I define LastEvaluatedKey?
If I define it inside gql I will get below error:

input LastEvaluatedKey {
          id: String
          timestamp: Int
}
OperationException (GraphQL Errors:
        Validation error of type NonExecutableDefinition: The LastEvaluatedKey definition is not executable.: Undefined location)

@micimize
Copy link
Collaborator

@zhaoyi0113 in graphql, inputs are defined in the schema. So, I would look at your schema and see what the method signature of posts is. The lastEvaluatedKey should have a predefined input type that you can reference in your query.

@zhaoyi0113
Copy link
Author

zhaoyi0113 commented May 20, 2020

I would say the schema is on the server side. So I don't need to define that in client side.
This is my schema:

type Mutation {
	sendPost(post: PostInput): Post
	savePostPhotos(id: ID!, paths: [String]): ID
}

type PaginationKey {
	id: String!
	timestamp: Long
}

input PaginationKeyInput {
	id: String!
	timestamp: Long
}

type Post {
	userId: String!
	message: String
	id: ID!
	timestamp: Long!
	userInfo: UserInfo
	photoPaths: [String]
	pstatus: Int
}

input PostInput {
	userId: String!
	message: String
}

type PostReqResponse {
	posts: [Post]
	lastEvaluatedKey: PaginationKey
}

type Query {
	presignedURL(id: ID!, count: Int!): [String]
	posts(size: Int, lastEvaluatedKey: PaginationKeyInput): PostReqResponse
	post(id: ID!): Post
}

type UserInfo {
	id: ID
	username: String
	firstName: String
	lastName: String
	name: String
	email: String
	picture: String
}

schema {
	query: Query
	mutation: Mutation
}

@micimize
Copy link
Collaborator

@zhaoyi0113 so, instead of LastEvaluatedKey, you want to use the input type PaginationKeyInput. So this should work:

await this.gqClient.query(QueryOptions(documentNode: gql('''
        query posts(\$size: Int, \$lastEvaluatedKey: PaginationKeyInput){
          posts(size: \$size, lastEvaluatedKey: \$lastEvaluatedKey) {
            posts {
              id,
              message,
              photoPaths,
              userInfo {
                username,
                picture
              }
            }
            lastEvaluatedKey {
              id
              timestamp
            }
          }
        }
      '''), variables: {
                'size': this.pageSize,
                'lastEvaluatedKey': this._lastEvaluatedKey.toJson(),
              }));

@zhaoyi0113
Copy link
Author

awesome, it fixes the issue. Thanks for checking my bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants