I am implementing a webpage with React and AWS Amplify.
I have the following definition in my schema.graphql file:
type Calendar #model {
id: ID!
name: String
description: String
url: String!
intervals: [Interval] #connection(keyName: "byCalendar", fields: ["id"])
}
I would like to get a calendar from its URL string. Unfortunately, the following code throws an error:
import { API, graphqlOperation } from "aws-amplify";
import * as queries from "../../graphql/queries";
await API.graphql(graphqlOperation(queries.getCalendar, { url: "some-url"}));
Variable "$id" of required type "ID!" was not provided.
From the error, providing the id is mandatory. However, I would like to be able to get an object from just the url.
How can I do that?
I am using the queries automatically generated by the amplify's cli.
/* eslint-disable */
// this is an auto generated file. This will be overwritten
export const getCalendar = /* GraphQL */ `
query GetCalendar($id: ID!) {
getCalendar(id: $id) {
id
name
description
url
intervals {
nextToken
}
createdAt
updatedAt
}
}
`;
export const listCalendars = /* GraphQL */ `
query ListCalendars(
$filter: ModelCalendarFilterInput
$limit: Int
$nextToken: String
) {
listCalendars(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
name
description
url
createdAt
updatedAt
}
nextToken
}
}
`;
Found the solution. I had to add a "byURL" key to the model like so:
type Calendar #model #key(name: "byURL", fields: ["url", "id"], queryField: "calendarByURL") {
id: ID!
name: String
description: String
url: String
intervals: [Interval] #connection(keyName: "byCalendar", fields: ["id"])
}
Then write a custom query using that new key (or have amplify to regenerate the queries based on the updated schema.graphql file):
export const getCalendarByURL = /* GraphQL */ `
query calendarByURL($url: String!) {
calendarByURL(url: $url) {
items {
id
name
description
url
intervals {
nextToken
}
createdAt
updatedAt
}
}
}
`;
And this would let me do:
await API.graphql(graphqlOperation(customQueries.getCalendarByURL, { url: "some-url"}));
Related
I'm trying to add a filter to the following graphql query and I'm just not able to figure out where to add the filter parameter. I went through the documentation but I'm clueless how to do it. I should also retain the limit and offset to do the pagination. I would like to filter by ID.
const data = await axios.post("http://localhost:1337/graphql", {
query: `query {
newsPostsConnection(limit: ${limit}, start: ${start}) {
values {
id
title
body
writtenBy
imageUrl
created_at
}
aggregate {
totalCount
}
}
}`
I think this link answers your question
Schema
type NewsPostsConnection {
id: String! #id
title: String!
body: String
writtenBy: String
imageUrl: String
created_at: DateTime
}
Query
query {
getNewsPostsConnection(id: $id) {
values {
id
title
body
writtenBy
imageUrl
created_at
}
aggregate {
totalCount
}
}
}
I am executing a GraphQL query:
export const userByName = /* GraphQL */ `
query employee(
$first_name: String
$sortDirection: ModelSortDirection
$filter: ModelUserFilterInput
$limit: Int
$nextToken: String
) {
employee(
first_name: $first_name
sortDirection: $sortDirection
filter: $filter
limit: $limit
nextToken: $nextToken
) {
items {
id
employee_type
first_name
last_name
createdAt
updatedAt
}
nextToken
}
}
`;
When I execute this query, I get this error:
sortDirection is not supported for List operations without a Sort key defined.
I am executing this query using this code:
const userInfo = await API.graphql(
graphqlOperation(employee, {
first_name: name,
sortDirection: 'DESC'
})
)
I'm trying to retrieve data, but the above error arises. I have also tried removing sortDirection, but I just get an empty array as a response.
const MUTATION_QUERY = gql`
mutation MUTATION_QUERY(
$name: bigint!
) {
insert_name(
objects: {
name: $name
}
) {
returning {
id
name
}
}
}
`;
const [onClick, { error, data }] = useMutation<{}, {}>(MUTATION_QUERY, {
variables: {
name: 1234,
},
});
My mutation query is inserting name in my table and autogenerating the id. On console logging the data variable I can view the fields id and name in the data object. But I am not able to access them them individually. How can I console.log "id". Thank you.
the console.log(data) looks like : {insert_name: {...}}
which expands to :
insert_name:
returning: Array(1)
0: {id: 1, name: 1234}
length: 1
_proto_: Array(0)
_typename: "insert_name_mutation_response
You can access the fields of an object with .
For example, if your object looks like this -
data = {
id: 1,
name: 'Jane',
}
You can get just the id with data.id
This works no matter how many layers deep your object may go, so take this example -
data = {
person: {
id: 1,
name: 'Jane',
}
}
You could get the id of person with data.person.id.
console.log(data.insert_name.returning[0].id) will give you the id returned.
For it to work in typescript we need to change the query to add the return type of data
const [onClick, { error, data }] = useMutation<{ReturnInsertNameProps}, {}>(MUTATION_QUERY, {
variables: {
name: 1234,
},
});
interface ReturnInsertNameProps {
insert_name: ReturnQueryProps;
}
interface ReturnProps {
returning: MessageProps[];
}
interface NameProps {
id: number;
name: number;
}
We can also use onCompleted method provided in useMutation if we want to process the result of the query.
Following Gatsby tutorial here https://www.gatsbyjs.org/docs/adding-tags-and-categories-to-blog-posts/ it is possible to filter posts by tag to create tag pages easily...
What I'm trying to achieve is to create index pages for posts having the same slug prefx :
/folder1/sub1/post-A
/folder1/sub1/post-B
/folder1/sub2/post-C
Will create 3 index pages :
/folder1/ (containing the three posts)
/folder1/sub1/ (containing post A and B)
/folder1/sub2/ (containing only post C)
This will use a query like :
export const query = graphql`
query tagListQuery($prefix: String, $skip: Int!, $limit: Int!) {
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
filter: { fields: { slug: { startsWith: $prefix } } }
limit: $limit
skip: $skip
) {
edges {
node {
id
frontmatter {
title
}
fields {
slug
}
}
}
}
}
`
But startsWith filtering does not exists :
"message": "Field \"startsWith\" is not defined by type
StringQueryOperatorInput."
Is there a way to filter using prefix matching with graphQL ?
Are you sure you got fields inside node? If so you should show us your schema (found in http://localhost:8000/___graphql), for example:
Anyway, I guess you want to query fileAbsolutePath:
query tagListQuery($prefix: String, $skip: Int!, $limit: Int!) {
allMarkdownRemark(sort: {order: DESC, fields: [frontmatter___date]}, fileAbsolutePath: {regex: $prefix}}, limit: $limit, skip: $skip) {
edges {
node {
id
frontmatter {
title
}
}
}
}
}
If you want to add startWith etc, you need to customize the schema.
I am using react-apollo on the front-end and graphcool on the backend. I have a mutation that creates a tutorial like so:
const CREATE_TUTORIAL_MUTATION = gql`
mutation CreateTutorialMutation(
$author: String
$link: String
$title: String!
$postedById: ID!
$completed: Boolean!
) {
createTutorial(
author: $author
link: $link
title: $title
postedById: $postedById
completed: $completed
) {
author
link
title
postedBy {
id
name
}
completed
}
}
`
It gets called in a submit handler like so...
this.props.createTutorialMutation({
variables: {
author,
link,
title,
completed: false,
postedById
}
})
Everything works wonderfully.
Now I want to add a set of tags to when I create a new tutorial. I created the input field and connected it so that the tags variable is an array of objects, each with a tag id and the tag text.
If I try and add the tags field to the mutation it needs a scalar type. But there is doesn't seem to be a scalar type for an array of objects.
If I pass the tag variable in as a parameter when I call the mutation how do I fill in the Scalar type field in the mutation ( on line 148 here https://github.com/joshpitzalis/path/blob/graphQL/src/components/Add.js) and in the schema?
I am new to graphQL and I understand that I might be approaching this completely the wrong way. If that is the case, how do I add an array of objects to a mutation in graphQL?
You should add a new Tag type to your schema file and connect it to Tutorial with a new relation:
type Tutorial {
author: String
completed: Boolean
link: String
title: String!
id: ID! #isUnique
createdAt: DateTime!
updatedAt: DateTime!
postedBy: User #relation(name: "UsersTutorials")
tags: [Tag!]! #relation(name: "TutorialTags")
}
type Tag {
id: ID!
tag: String!
number: Int!
tutorials: [Tutorial!]! #relation(name: "TutorialTags")
}
Then you can create a new tutorial and new tags using a nested create mutation like this:
const CREATE_TUTORIAL_MUTATION = gql`
mutation CreateTutorialMutation(
$author: String
$link: String
$title: String!
$tags: [TutorialtagsTag!]!
$completed: Boolean!
$postedById: ID!
) {
createTutorial(
author: $author
link: $link
title: $title
tags: $tags
completed: $completed
postedById: $postedById
) {
author
link
title
postedBy {
id
name
}
completed
tags {
id
text
}
}
}
`
This post gives more background about other approaches and their trade-offs: https://www.graph.cool/forum/t/how-do-i-add-an-array-of-objects-to-a-mutation-in-apollo-react/365/6?u=nilan
What i understand by your requirement is that if you have the following code
const user = {
name:"Rohit",
age:27,
marks: [10,15],
subjects:[
{name:"maths"},
{name:"science"}
]
};
const query = `mutation {
createUser(user:${user}) {
name
}
}`
you must be getting something like
"mutation {
createUser(user:[object Object]) {
name
}
}"
instead of the expected
"mutation {
createUser(user:{
name: "Rohit" ,
age: 27 ,
marks: [10 ,15 ] ,
subjects: [
{name: "maths" } ,
{name: "science" }
]
}) {
name
}
}"
If this is what you wanted to achieve, then gqlast is a nice tag function which you can use to get the expected result
Simply grab the js file from here and use it as:
const user = {
name:"Rohit",
age:27,
marks: [10,15],
subjects:[
{name:"maths"},
{name:"science"}
]
};
const query = gqlast`mutation {
createUser(user:${user}) {
name
}
}`
The result stored in the variable query will be :
"mutation {
createUser(user:{
name: "Rohit" ,
age: 27 ,
marks: [10 ,15 ] ,
subjects: [
{name: "maths" } ,
{name: "science" }
]
}) {
name
}
}"