GraphQL alias top-level data into a nested object - graphql

Currently I’m querying the currentUser for a city.
query user {
currentUser {
city
}
}
However the requirements of my front-end requires the city as an object containing label and value.
// this doesn’t work, but is the idea…
query user {
currentUser {
city {
label: city
value: city
}
}
}
Is this possible to do at the GraphQL query level?

I haven't seen your database model, but you could have a City model, something like:
type City {
id: ID! #unique
label: String
value: String
}
Then, in your User model you could do something like this:
type User {
id: ID! #unique
.... other User fields
city: City
}
With that schema, you would be able to query the city values inside an user:
query user {
currentUser {
city {
label
value
}
}
}
You should adapt that to your needs, but that's the main idea that I think you are looking for.

Related

Querying Many-To-Many Relationships in AWS Amplify

I have two models in my graphql schema and the one I am trying to query on, Sessions, has two #belongsTo directives (read on a forum this matters). I can successfully save these models and view them on the AWS AppSync Queries Tab where I can query getSessions successfully BUT when I try to the exact same query locally following these docs:
(https://docs.amplify.aws/lib/graphqlapi/advanced-workflows/q/platform/flutter/#combining-multiple-operations)
I get an error locally:
type "Null" is not a subtype of type 'string'
What am I doing wrong and how do I fix this so I can successfully retrieve my nested query:
Here are my models as a reference:
Sessions:
type Session
#model
#auth(
rules: [
{ allow: public }
{ allow: owner }
{ allow: groups, groups: ["Admin"] }
]
) {
id: ID!
name: String
numPeoplePresent: Int
notes: String
eIdReader: String
weighTiming: String
cows: [Cow] #manyToMany(relationName: "CowSession")
proceduresID: ID
procedures: Procedures #hasOne(fields: ["proceduresID"])
}
Cow:
type Cow
#model
#auth(
rules: [
{ allow: public }
{ allow: owner }
{ allow: groups, groups: ["Admin"] }
]
) {
id: ID!
name: String!
RfId: String
weight: [Float!]!
temperament: [Int]
breed: String
type: String
dateOfBirth: AWSDate
sessions: [Session] #manyToMany(relationName: "CowSession")
procedures: [Procedures] #manyToMany(relationName: "CowProcedures")
}
This is the query that is causing the error:
const getSession = 'getSession';
String graphQLDocument = '''query getSession(\$id: ID!) {
$getSession(id: \$id) {
numPeoplePresent
notes
name
eIdReader
id
owner
proceduresID
updatedAt
weighTiming
cows {
items {
cow {
RfId
}
}
}
}
}''';
final getSessionRequest = GraphQLRequest<Session>(
document: graphQLDocument,
modelType: Session.classType,
variables: <String, String>{'id': sessID}, //parameter of the current session can hardcode to whatever you need here
decodePath: getSession,
);
final response =
await Amplify.API.query(request: getSessionRequest).response;
print('Response: ${response.data}');
The wonderful people at amplify answered this quickly so I will relay the information here:
the problem was the intermediary ids were not included in my local query so it was unable to retrieve the nested Cows. Updated query looks like this:
getSession = 'getSession';
String graphQLDocument = '''query getSession(\$id: ID!) {
$getSession(id: \$id) {
numPeoplePresent
notes
name
eIdReader
id
owner
proceduresID
updatedAt
weighTiming
cows {
items {
id <-- needed this one
cow {
id <-- and this id too
RfId
breed
dateOfBirth
name
type
weight
}
}
}
}
}''';

Query Appsync graphql with 3 different combinations

I am using appsync with amplify and trying to figure out how to query based on two different selectors. Basically I need to either query all if neither county or facility are supplied, query with county while facility is empty, or query with facility while county is empty. I thought I could wrap this into 1 query but it doesn't seem like I can. My appsync schemas look like this.
type Client
#model
#key(name: "clientByCountyOrFacility", fields: ["county", "facility"], queryField: "getClientsByCountyOrFacility")
#searchable {
id: ID!
facility: String!
county: String!
products: [Product] #connection(name: "ClientProducts")
}
type Product
#model
#searchable {
id: ID!
client: Client #connection(name: "ClientProducts")
}
I can get this to work by using (below query) but I am worried this will run into the 100 scan limit because it uses the listClients query underneath. Possibly if there was an easy way to change that could be a solution but it seems the files in amplify are autogenerated.
query getClientsByCountyOrFacility($county: String = "", $facility: String = "") {
listClients(filter: {
county: {
contains: $county
}
facility: {
contains: $facility
}
}) {
items {
id
products {
items {
id
}
}
}
}
}
I added the #key to see if I could create an index but it doesn't like that and I'm at a lose for how to acquire the data. How do I go about building this schema and query to get the data back?

GraphQL mutation - confusion designing gql tag for Apollo Client

I need help figuring out the GraphQL tag for use with Apollo Client. The Docs don't go far beyond the most basic use case for mutations.
My goal is to have the only required input be an email. If the other variables are present, I would like those to be accepted and create a proposal with all that information.
I have the mutation (in both only email and full variables scenarios) working successfully on the GraphQl Playground (if it helps, you can find it here and test it out, look at the schema, etc.,): https://prisma2-graphql-yoga-shield.now.sh/playground)
mutation {
createOneProposal(
data: {
email: "fake#gmail.com"
name: "Sean"
types: {
create: {
model: PURCHASE
name: "e-commerce"
cost: 600
services: {
create: [
{ service: "Responsive web design" }
{ service: "Another service!" }
{ service: "And yet another service!" }
]
}
}
}
}
) {
created_at
proposal_id
types {
cost
model
name
type_id
services {
service
service_id
}
}
}
}
Producing as a result:
{
"data": {
"createOneProposal": {
"created_at": "2020-02-27T21:28:53.256Z",
"proposal_id": 35,
"types": [
{
"cost": 600,
"model": "PURCHASE",
"name": "e-commerce",
"type_id": 6,
"services": [
{
"service": "Responsive web design",
"service_id": 10
},
{
"service": "Another service!",
"service_id": 11
},
{
"service": "And yet another service!",
"service_id": 12
}
]
}
]
}
}
}
My initial design for the gql tag:
export const NEW_PROPOSAL = gql`
mutation createOneProposal(
$email: String!
$name: String
$cost: Int
$model: Model
$service: Service
) {
createOneProposal(
email: $email
name: $name
cost: $cost
model: $model
service: $service
) {
created_at
proposal_id
types {
services {
service_id
}
}
}
}
`;
But, I get a lot of errors with this.
{"errors":[
{"Variable "$service" cannot be non-input type `"Service`".","locations":[{"line":1,"column":97}]},
{"Unknown argument "email" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":21}]},
{"Unknown argument "name" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":36}]},
{"Unknown argument"cost" on field "createOneProposal\" of type "Mutation`".","locations":[{"line":2,"column":49}]},
{"Unknown argument "model" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":62}]},
{"Unknown argument "service" on field "createOneProposal`" of type "Mutation`".","locations":[{"line":2,"column":77}]},
{"Field "createOneProposal" argument "data" of type "ProposalCreateInput!`" is required, but it was not provided.","locations":[{"line":2,"column":3}]}]}
So, how can I go about this... I figured out the query version (much easier...), but I just can't figure this out!
My schema, if it helps:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("MYSQL_URL_PRISMA2")
}
model Post {
content String #default("")
created_at DateTime #default(now())
post_id Int #default(autoincrement()) #id
published Boolean #default(false)
published_at DateTime?
title String #default("")
author User
}
model Profile {
bio String?
profile_id Int #default(autoincrement()) #id
user_id User
}
model Proposal {
email String #unique
name String?
proposal_id Int #default(autoincrement()) #id
created_at DateTime #default(now())
types Type[]
}
model Type {
cost Int?
name String?
model Model? #default(SUBSCRIPTION)
services Service[]
type_id Int #default(autoincrement()) #id
proposal_id Proposal
}
model Service {
service_id Int #default(autoincrement()) #id
service String?
type_id Type
}
model User {
email String #default("") #unique
name String #default("")
password String #default("")
role Role #default(USER)
user_id Int #default(autoincrement()) #id
posts Post[]
profiles Profile[]
}
enum Role {
USER ADMIN
}
enum Model {
SUBSCRIPTION PURCHASE CUSTOM
}
GraphQL types are categorized as either input types or output types. Input types are used for inputs like variable definitions or argument definitions. Output types are used for typing fields, which are what compose the actual response. Certain types, like scalars and enums, can be used as either an input or an output. However, with objects, there are output object types (sometimes referred to just object types or objects) and input object types.
Service is an output type, so it can't be used where an input type is expected (in this case, a variable definition). Examine the schema generated by Prisma to determine the appropriate type to use.
Thanks to some very needed direction from #xadm, I figured out the structure of the tag! For anyone who comes across this in the future:
mutation createOneProposal($input: ProposalCreateInput!){
createOneProposal(data:$input){
created_at
name
email
proposal_id
type{
cost
description
model
name
type_id
services{
service
cost
service_id
}
}
}
}

Entity Association syntax issue with graphql queries

I am trying to understand graphql's query and mutation syntax. Given this example:
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String
author: Author
votes: Int
}
type Query {
posts: [Post]
author(id: Int!): Author
}
What should the queries look like to associate a post with the author? Is this where connections come into play or is that something else? Here is my attempt at trying to solve the problem but to avail.
mutation createAuthor {
createAuthor(input: {
id: 123
firstName: "Bob"
lastName: "Smith"
}) {
id
firstName
lastName
}
}
query listAuthors {
listAuthors {
items {
id
firstName
lastName
}
}
}
mutation createPost {
createPost(input: {
id: 12345
title: "Title"
votes: 345
author: {
lastName: {
contains: "Bob"
}
}
}) {
id
title
votes
author {
id
firstName
lastName
}
}
}
Any help on this would be appreciated. My Goal is to Query an author and return all of the post's associated with that author as well as create a Post Mutation that adds a post to an author.
There are 2 questions in one, so I'll answer in the order there were asked.
1. return all of the posts associated with an author
Your schema looks correct. The query would look like:
query {
author(id: 1) {
id
posts {
id
title
}
}
}
2. create Post and attach to an author
In your example if you want to expose an interface to create a Post, then you would have to expose a mutation field in your schema
e.g:
type Mutation {
createPost(input: CreatePostInput): Post
}
if you want at the same time of creating a post, to also attach it to an author then you could add the authorId as part of the input, here we only want to attach the Post to an existing Author:
input CreatePostInput {
title: String
authorId: ID!
votes: Int
}
of course this is only the interface definition. We need to actually create the Post and link it to the Author inside the resolver.
The mutation query will look like:
mutation createPost {
createPost(input: {
title: "Title"
votes: 345
authorId: "authorId1"
}) {
id
title
votes
author {
id
firstName
lastName
}
}
}
Hope that helps!

join 3 tables using graphql query

I want to join 3 tables just like we do in mysql based on primary and foreign keys.
Can I do such using graphql(http://graphql.org/)
My table structure along with graphql query is below. Thanks
query($companyId:String){
Data{
reach{
department {
departmentId
departmentName
description
}
companyDepartment(companyId:$companyId) {
primaryId
departmentId
companyId
createdDate
modifiedDate
modifiedBy
}
company(companyId:$companyId) {
companyId
companyName
}
}
}
}
You must break your mind and think in Graph way model :)
Type Company(node) <- CompanyDepartmentConection (name of connection edge) -> Type Department(node)
based on this very useful article, anyway i do for you eg. Schema
Concept
interface Node {
id: ID!
name: String
}
type Company implements Node {
id: ID!
name: String
departmentsConnection: CompanyDepartmentConnection
}
type CompanyDepartmentConnection {
pageInfo: PageInfo!
edges: [CompanyDepartmentEdge]
}
type CompanyDepartmentEdge {
cursor: String!
node: Company
linkedAt: DateTime
}

Resources