I'm trying to learn GraphQL (& node.js & MongoDB etc.). I cant get this simple nested query to return results :
query getLocationByPerson {
People {
firstName
lastName
service {
location
}
}
}
I only get the first level fields, like:
{
"data": {
"People": [
{
"firstName": "xxx",
"lastName": "XXXXX",
"service": null
}
}
Here's my schema:
type Query {
People: [PeopleObject]!
PeopleByName(lastName: String!): [PeopleObject]
PeopleByID(id:ID!): [PeopleObject]
Service: [ServiceObject]
ServiceByID(id:ID!): [ServiceObject]
}
type PeopleObject {
id: ID!
Xid: String!
firstName: String!
lastName: String!
email: String!
serviceId: String
apps: [String]
service: [ServiceObject]
}
type ServiceObject {
id: ID!
name: String!
location: String!
}
And my resolver:
const queries = {
People: () => People.find({}),
PeopleByName: (root,args,context,info) => People.find({lastName: args.lastName}),
PeopleByID: (root,args,context,info) => People.find({_id: args.id}),
Service: () => Service.find({}),
ServiceByID: (root,args,context,info) => Service.find({_id: args.id})
};
Any idea what am I doing wrong?
You need to pass the reference for the location object in service which is same as you mongoose model(i assume you are using mongoose). After passing the reference you can add populate(refernce).exec() in your service query Refer this
Your syntax are dame good for getting any data from graphql
type Query {
People: [PeopleObject]!
}
type PeopleObject {
id: ID!
Xid: String!
firstName: String!
lastName: String!
email: String!
serviceId: String
apps: [String]
service: [ServiceObject]
}
type ServiceObject {
id: ID!
name: String!
location: String!
}
for Simplicity
type Query {
People: [{
id: ID!
Xid: String!
firstName: String!
lastName: String!
email: String!
serviceId: String
apps: [String]
service: [{
id: ID!
name: String!
location: String!
}]
}]!
}
But you have return only people
People: () => People.find({}),
You should return service array object to get that return object with People
People: () => return something Like below result.
[{
id: '5c5ac87e5e4d85ae77de9c50'
Xid: 'xx'
firstName: 'yyy'
lastName: 'zzz'
email: 'xxx#gmail.com'
serviceId: '5c5ac87e5e4d85ae77de9c51'
apps: ['testing', 'google']
service: [{
id: 5c5ac78d5e4d85ae77de9c4f,
name: 'Tester',
location: 'US America',
}, {}]
}, {}]
If you using mongoose use aggregation to get data from mongoBD.
Related
I was working on an existing project using amplify with GraphQl API.
The query shows issues with #Key as Your GraphQL Schema is using "#key" directive from an older version of the GraphQL Transformer . Since I am new to graphQL, what should I change to make this work?
Thanks
Error:
✖ An error occurred when pushing the resources to the cloud
🛑 An error occurred during the push operation: Your GraphQL Schema is using "#key" directive from an older version of the GraphQL Transformer. Visit https://docs.amplify.aws/cli/migration/transformer-migration/ to learn how to migrate your GraphQL schema.
Query:
type KeyValuePair {
key: String!
value: String
}
type Template
#model
#auth(rules: [ {allow: owner } ]) {
id: ID!
name: String!
description: String
provision_style: String!
status: String!
params: [KeyValuePair]
resources: [KeyValuePair]
}
type Asset
#model
#auth(rules: [ {allow: owner } ])
#key(name: "categoryTypeIndex", fields: ["category", "type"], queryField: "assetsByCategoryAndType")
#key(name: "categoryNameIndex", fields: ["category", "name"], queryField: "assetsByCategoryAndName")
#key(name: "categoryStatusIndex", fields: ["category", "status"], queryField: "assetsByCategoryAndStatus") {
id: ID!
parent: ID
category: String!
type: String!
name: String!
description: String
status: String
template: String
details: [KeyValuePair]
}
type Contract
#model
#auth(rules: [ {allow: owner } ])
#key(name: "tenantAssetIndex", fields: ["tenantId", "assetId"], queryField: "contractsByTenantAndAsset")
#key(name: "tenantNameIndex", fields: ["tenantId", "name"], queryField: "contractsByTenantAndName")
#key(name: "tenantStatusIndex", fields: ["tenantId", "status"], queryField: "contractsByTenantAndStatus") {
id: ID!
type: String!
tenantId: String!
assetId: String!
name: String!
description: String
status: String
details: [KeyValuePair]
resources: [KeyValuePair]
}
type PlatformEvent
#model
#auth(rules: [ {allow: owner } ])
#key(name: "contractTypeIndex", fields: ["contractId", "type"], queryField: "eventsByContractAndType")
#key(name: "contractSourceIndex", fields: ["contractId", "sourceId"], queryField: "eventsByContractAndSource")
#key(name: "sourceTypeIndex", fields: ["sourceId", "type"], queryField: "eventsBySourceAndType") {
id: ID!
type: String!
contractId: String!
sourceId: String!
content: String!
details: [KeyValuePair]
}
AWS provides a migration guide: https://docs.amplify.aws/cli/migration/transformer-migration/ but unfortunately they don't specify how to actually set your API to use the new/old version.
If you look in your amplify folder you will find a cli.json file, to set your backend to use version 1 of the GraphQLTransformer you simply need to edit the file and set the following two properties:
"features": {
"graphqltransformer": {
...
"useexperimentalpipelinedtransformer": false,
"transformerversion": 1,
...
},
From there you simply amplify push and assuming you've catered for all of the changes the migration guide describes it will update your endpoint correctly.
EDIT: For those looking to upgrade to V2 instead of downgrading to V1 you will need to set the properties as follows:
"features": {
"graphqltransformer": {
...
"useexperimentalpipelinedtransformer": true,
"transformerversion": 2,
...
},
This should make your life easy.
Working with amplify datastore and edited schema.graphql as following and when I enter "amplify codegen models" I get this error "Error: Expected scalar and got User" However the code was generated successfully. How would I be able to fix this error?
type User
#model
#key(name: "ByEmail", fields: ["email"], queryField: "userByEmail")
#auth(rules: [{ allow: owner }]) {
id: ID!
email: String!
gender: String!
birthdate: String!
faceImage: String
favoriteAvatar: [Avatar] #connection(fields: ["avatarId"])
totalVideoTransform: Int
registerAt: AWSDateTime!
}
type Avatar
#model
#key(name: "ByAvatrId", fields: ["avatarId"], queryField: "avatarByAvatarId")
#auth(rules: [{ allow: owner, ownerField: "favoriteUser", operations: [create, update, read] }]) {
id: ID!
avatarId: String!
gender: String!
favoriteUser: [User] #connection(fields: ["email"])
totalVideoTransform: Int
}
type UserLoginLog
#model
#key(name: "ByUser", fields: ["user"], queryField: "userLoginLogByUser")
#auth(rules: [{ allow: owner, operations: [create] }]) {
id: ID!
user: User #connection(fields: ["email"])
loginAt: AWSDateTime!
}
type VideoTransformLog
#model
#key(name: "ByUser", fields: ["user"], queryField: "videoTransformLogByUser")
#auth(rules: [{ allow: owner, operations: [create] }]) {
id: ID!
user: User #connection(fields: ["email"])
avatar: Avatar #connection(fields: ["avatarId"])
videoTransformAt: AWSDateTime!
}
In your types "UserLoginLog" and "VideoTransformLog", remove "user" from the #key(... fields).
So don't place names that correspond to a type in fields[].
So I have 3 collections in my schema
type User #model(subscriptions: null) {
id: ID!
name: String
email: String
events: [EventUser] #connection(keyName: "byUser", fields: ["id"])
}
type Event #model
#key(name: "byApiKey", fields: ["apiKey"])
#key(name: "byOrganization", fields: ["organizationID"], queryField: "eventByOrganization")
{
id: ID!
apiKey: ID!
title: String
participants: [EventUser] #connection(keyName: "byEvent", fields: ["id"])
}
type EventUser #model
#key(name: "byUser", fields: ["userID"], queryField: "eventByUser")
#key(name: "byEvent", fields: ["eventID"], queryField: "userByEvent") {
id: ID!
userID: ID!
eventID: ID!
user: User! #connection(fields: ["userID"])
event: Event! #connection(fields: ["eventID"])
}
And I am trying to search the EventUser collection by eventID and user.name. Is there some piece of amplify that can enable me search by the user.name and return the EventUser collection?
I set up prisma with a graphql yoga server and have both GraphQL playgrounds available.
I could successfully create a conversation that I'm now trying to retrieve. I can't get this simple resolver to work in the Yoga GraphQL Playground:
const resolvers = {
Query: {
conversation(parent: any, { id }: { id: string }, { prisma }: Context) {
return prisma.conversation( { id } )
}
},
Mutation: mutation
}
I used this query:
query getConversation {
conversation(where: {
id: "cjrqzinj4004e0a30ch4pccml"
}) {
id
title
}
}
Error message is:
{
"data": {
"conversation": null
},
"errors": [
{
"message": "You provided an invalid argument for the where selector on Conversation.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"conversation"
],
"code": 3040,
"requestId": "local:cjrsahjoo00ai0a30a5y8mnvp"
}
],
"extensions": {}
}
The query works in the Prisma GraphQL playground.
Here is my data model:
type User {
id: ID! #unique
oauthId: String! #unique
display: String!
picture: String!
likes: [Comment!]! #relation(name: "Likes")
dislikes: [Comment!]! #relation(name: "Dislikes")
bookmarks: [Comment!]! #relation(name: "Bookmarks")
authorOf: [Comment!]! #relation(name: "Author")
starterOf: [Conversation!]! #relation(name: "Starter")
}
type Attachment {
id: ID! #unique
name: String!
createOn: DateTime!
mediaType: String!
comment: Comment! #relation(name: "Attachments")
}
type Comment {
id: ID! #unique
author: User! #relation(name: "Author")
content: String!
createDate: DateTime!
parentConversation: Conversation #relation(name: "Conversation")
parentComment: Comment #relation(name: "Replies")
comments: [Comment!]! #relation(name: "Replies")
bookmarkedBy: [User!]! #relation(name: "Bookmarks")
likedBy: [User!]! #relation(name: "Likes")
dislikedBy: [User!]! #relation(name: "Dislikes")
attachments: [Attachment!]! #relation(name: "Attachments")
}
enum ParentType {
Organization,
Portfolio,
Project,
WbsComponent,
WorkItem
}
type Parent {
id: ID! #unique
parent: String! #unique
type: ParentType!
conversations: [Conversation!]! #relation(name: "Parent")
}
type Conversation {
id: ID! #unique
parent: Parent! #relation(name: "Parent")
organization: String!
title: String!
author: User! #relation(name: "Starter")
createdOn: DateTime!
comments: [Comment!]! #relation(name: "Conversation")
}
Can try to pass where property to the prisma client
const resolvers = {
Query: {
conversation(parent: any, { id }: { id: string }, { prisma }: Context) {
return prisma.conversation( { where: { id } )
}
},
Mutation: mutation
}
I got the answer from the Prisma forum. I was doing my destructuring wrong (note that ConversationWhereUniqueInput is a type provided by prisma):
export const conversation = (
parent: any,
{ where: { id } }: { where: ConversationWhereUniqueInput },
{ prisma }: Context
): ConversationPromise => {
return prisma.conversation({ id })
}
I have the following GraphQL schema. It has Books and Authors with a many to many relationship. How do I create a new Book mutation for an existing Author?
schema
type Author implements Node {
books: [Book!]! #relation(name: "BookAuthors")
createdAt: DateTime!
id: ID! #isUnique
name: String!
updatedAt: DateTime!
}
type Book implements Node {
authors: [Author!]! #relation(name: "BookAuthors")
createdAt: DateTime!
id: ID! #isUnique
title: String!
updatedAt: DateTime!
}
mutation
mutation CreateBook($title: String!, $authors: [Author!]) {
createBook(
title: $title,
authors: $authors,
) {
id
title
}
}
variables
{
"title": "Ryans Book",
"authors": ["cj5xti3kk0v080160yhwrbdw1"]
}
This is apparently called a 'connect mutation'.
https://www.graph.cool/docs/reference/simple-api/nested-connect-mutations-tu9ohwa1ui/
mutation CreateBook($title: String!, $authorIds: [ID!]) {
createBook(
title: $title,
authorIds: $authorIds,
) {
id
title
}
}