Simple graphQL query gives error - angularjs

I am trying to use graphql for one of the GET request based on an id. Here's the code:
const { graphql, buildSchema } = require('graphql');
EmployeeService.prototype.getEmployee = function() {
// Construct a schema
const schema = buildSchema(`
type Query {
employee(id="12345") {
id
items {
id
name
}
}
}
`);
// The root provides a resolver function
let root = {
employee: () => id
};
// Run the GraphQL query
graphql(schema, '{ employee }', root).then((response) => {
console.log(response);
});
};
Trying to follow the documentation on http://graphql.org/graphql-js/.
I get a GraphQL error: "Syntax Error GraphQL request (3:19) Expected :, found =↵↵2: type Query {↵3: employee (id="12345") {↵ ^↵4: id↵"
Please advise.

You are maybe mixing things a little bit up. The schema and resolvers are part of your API and are not needed to make a query on a client. Just for demonstration purposes here a valid schema definition (that would normally run on a API server):
let schema = buildSchema(`
type Item {
id: Int!
name: String!
}
type Employee {
id: Int!
items: [Item]
}
type Query {
employee(id: Int!): Employee
}
`);
You then define your types and resolvers (simplified examples):
class Employee {
constructor(id, items) {
this.id = id;
this.items = items;
}
}
let root = {
employee: ({id}) => {
return new Employee(id, [{id: 1, name: 'Item 1'}, {id: 2, name: 'Item2'}]);
}
};
You can then run a query:
const query = `
{
employee(id: 1) {
id,
items {
id,
name
}
}
}
`;
graphql(schema, query, root).then((response) => {
console.log(response.data);
});
To run actual queries against a remote API have a look at GraphQL clients like Apollo or lokka

Related

Fetch query is sending on the server twice

The result of the mutation should update the data without an unnecessary request to the server, I do not understand what needs to be corrected so that the data is not fetched twice, but taken from the cache.
const [createEvent, { loading }] = useMutation(CREATE_GOOD_MUTATION, {
variables: values,
update(proxy, result) {
// TODO: remove goods from cache
const data = proxy.readQuery({
query: FETCH_ITEMS_QUERY,
});
let newData = [...data.events];
newData = [result.data.events, ...newData];
proxy.writeQuery({
query: FETCH_ITEMS_QUERY,
data: {
...data,
events: {
newData,
},
},
});
},
// refetchQueries: [
// {
// query: FETCH_ITEMS_QUERY,
// },
// ],
onError(err) {
setErrors(err.message);
},
});
enter image description here
Mutation to create a new good:
CREATE_GOOD_MUTATION = gql`
mutation createEvent(
$title: String!
$description: String!
$price: String!
$autor: String!
$pageNumber: String!
$publishYear: String!
) {
createEvent(
eventInput: {
title: $title
description: $description
price: $price
autor: $autor
pageNumber: $pageNumber
publishYear: $publishYear
}
) {
title
description
price
}
}
`;
Query to display all products:
FETCH_ITEMS_QUERY = gql`
query events {
events {
id
title
description
price
}
}
`;
I need to fetch it once, when I try to create a new good by mutation and display all products from the cache, without an additional request.
You should use proxy.modify instead of proxy.readQuery/proxy.writeQuery.
Using cache.modify
Making cache updates with mutation.update function
Try to change your mutation update function to something like this:
update(proxy, result) {
proxy.modify({
fields: {
events(existingEvents = []) {
return [...existingEvents, result.data.createEvent];
}
}
})
},

GraphQL, ReactJs - unable to retrieve data when passing parameter to Query

I'd like to retrieve the _id of a document in my mongodb database using a graphql query.
Here is my query:
query {
getTeamRegistrationID(teamName:"Patriots") {
_id
}
}
And the result:
{
"data": {
"getTeamRegistrationID": []
}
}
This should return the ObjectID of the document from the mongodb database.
Here's my graphql schema:
const typeDefs = gql`
type TeamRegistration {
_id: ID,
teamName: String
},
type Query {
getTeamRegistrationID(teamName: String): [TeamRegistration]
}`
My resolver:
const resolvers = {
Query: {
getTeamRegistrationID: (parent, teamRegistration) => TeamRegistration.find({ teamName: teamRegistration.teamName })
}
}
I can't figure out what I'm doing wrong here. Is there something I'm missing? Thanks in advance!

Data Relationships and Connection Types with Mutations in Prisma, GraphQL, and Apollo

Sorry for the long post, but I tried to be as detailed as possible.
How can I edit my current model, schema, and resolver to be able to save/connect a related type (Vendor) to my created type (Item) via a web form?
I want to create an inventory item and select a vendor to be associated with that item.
I have a Prisma data model like so (I've other fields for simplicity because I have no trouble saving the other fields; it's just with other types where there is a relation)...
Items may or may not have a vendor associated with them. Vendors may or may not have a list of items currently associated with them.
type Item {
id: ID! #id
name: String!
description: String!
vendor: Vendor
}
type Vendor {
id: ID! #id
items: [Item!]
}
I have a graphql schema like this (compare to modified schema at the end of this question)...
type Mutation {
createItem(
name: String!
description: String!
): Item!
}
My resolver:
async createItem(parent, args, ctx, info) {
const item = await ctx.db.mutation.createItem(
{
data: {
...args,
},
}, info);
return item;
}
My React component contains the following:
const CREATE_ITEM_MUTATION = gql`
mutation CREATE_ITEM_MUTATION(
$name: String!
$description: String!
) {
createItem(
name: $name
description: $description
) {
id
name
description
vendor {
id
}
}
}
`;
const ALL_VENDORS_QUERY = gql`
query ALL_VENDORS_QUERY {
vendors {
id
}
}
`;
Later on down the web page in my HTML form, I have:
<Query query={ALL_VENDORS_QUERY}>
{({ data, loading }) => (
<select
id="vendor"
name="vendor"
onChange={this.handleChange}
value={this.state.vendor}
>
<option>Vendor</option>
{data.vendors.map(vendor => (
<option key={vendor.id} value={vendor.id}>{vendor.name}</option>
))}
</select>
)}
</Query>
I just don't know how to connect the vendor to the item through a form submission. I can get it working if I hard code the vendor id in my resolver like so:
async createItem(parent, args, ctx, info) {
const item = await ctx.db.mutation.createItem(
{
data: {
vendor: {
connect: { id: "ck7zmwfoxg4b70934wx8kgwkx" } // <-- need to dynamically populate this based on user input from the form
},
...args,
},
}, info);
return item;
}
...but that obviously is not what I want.
To me, it makes the most sense to modify my schema like so:
createItem(
name: String!
description: String!
vendor: Vendor <--- added
): Item!
But when I do that I get this:
Error: The type of Mutation.createItem(vendor:) must be Input Type but got: Vendor.
How can I edit my current model, schema, and resolver to be able to save/connect a vendor ID that is selected on the form?
The answer to my problem was found here: How to fix 'Variable "$_v0_data" got invalid value' caused from data types relation - Mutation Resolver
I was spreading the args (...args) while also passing the vendor argument.
Here is my updated mutation:
createItem(
name: String!
description: String!
vendorId: ID
): Item!
and its resolver:
async createItem(parent, {name, description, vendorId}, ctx, info) {
const item = await ctx.db.mutation.createItem(
{
data: {
vendor: {
connect: { id: vendorId }
},
name,
description,
},
}, info);
return item;
}
Boom! 💥

How to create field resolver on RedwoodJS

RedwoodJS automatically maps GraphQL queries resolvers to api/src/services. How do I create a field resolver for a given GraphQL type?
Suppose I have this schema:
type Person {
name: string!
birthDate: DateTime!
age: Int!
}
But only name and birthDate are stored in the database.
Using graphql-tools I would write my resolvers like this:
const resolvers = {
Query: { ... },
Mutation: { ... },
Person: {
age(person) {
return new Date().getFullYear() - person.birthDate.getFullYear();
},
},
};
PS: I know the age formula is wrong.
PS2: I'm using age here for the sake of simplicity, imagine this is expensive to compute or get from database.
It's almost identical to the way you do it with graphql-tools.
You export an object with the same name as your type in your service:
// services/person.js
export const Person = {
age: (_args, { root }) {
return new Date().getFullYear() - root.birthDate.getFullYear();
},
}
As an aside, you could also export a resolvers in the person.sdl.js file (But services take precendence):
// graphql/person.sdl.js
export const schema = gql`/* ... */`
export const resolvers = {
Query: {},
Mutation: {},
Person: {},
}
Edit: I misunderstood the question, this answer just covers creating query + mutation resolvers, not a resolver for a computed field.
To create a field resolver, you'll need to decide whether you're creating a resolver for a query, or a handler for a mutation.
We can use the following schema as an example:
export const schema = gql`
type Person {
id: String!
name: String!
age: Int!
}
type PersonInput {
name: String
age: Int
}
type Mutation {
createPerson(input: PersonInput!): Person
}
type Query {
people: [Person]
person(id: String!): Person
}
`
If the above schema is stored in a file called persons.sdl.js, in the api/src/graphql directory, you can implement the queries and mutations in a file called persons.js in the api/src/services/persons directory.
// implements Mutation.createPerson(...)
export const createPerson({ input }) => {
return db.person.create({
data: input
})
}
// implements Query.people
export const people = () => {
return db.person.findMany()
}
// implements Query.person(...)
export const person = ({ id }) => {
return db.person.findOne({
where: { id }
})
}

How can I specify optional query filters in Prisma?

I am building an application with React, Apollo and Prsima that allows users to filter cars by model, brand, price... I know (for example) how to filter cars by brand:
const GET_CARS = gql`
query FilterCars($brandId: ID){
cars(where: {
model : { brand: { id: $brandId } }
}) {
id
model {
name
brand {
name
}
horses
}
year
km
price
...
}
`;
And in the component:
const CarList = (props) => {
const { data, loading, error } = useQuery(GET_CARS, {
variables: {
brandId: "exampleBrandId"
}
})
...
}
The problem is, that some parameters are optional: maybe the user does not care about the brand, or the model, or the price... So then all cars should appear: If no brand is selected, cars of all brands should appear; If no price is selected, cars of all prices should appear...
How can I do that? Something like:
query FilterCars($brandId: ID){
cars(where: {
model : { brand: { id: $brandId || all_brand_ids } }
}) {
...
}
}
I have investigated a and found a possible solution, but the custom input that the post refers to is not generated in my prisma.
getCars(parent, args, {prisma}, info){
const queryArgs ={}
if(args.brandId){
queryArgs ={
where: {
model: {
id: args.brandId
}
}
}
}
if(args.price){
queryArgs={
...queryArgs,
where: {
...queryArgs.where
//What every you want to add
}
}
}
return prisma.query.cars(queryArgs, info)
}
You can check on the Backend your args. And create a flexible obj to query for...
The answer from #Toiz is feasible. However, what if the number of parameters increases so that multiple if-statements are needed?
I suggest using undefined.
As mentioned in prisma official docs here, you can use undefined to optioanally exclude a field from query.
For example,
where: {
model : {
brand: {
id: $brandId != null ? $brandId : undefined
}
}
}
const GET_CARS = gql`
query FilterCars($brandId: ID){
cars(where: {
model : { brand: { id: $brandId } }
}) {
id
model {
name
brand {
name
}
horses
}
year
km
price
}
`;
const CarList = (props) => {
const { data, loading, error } = useQuery(GET_CARS, {
variables: {
brandId: "exampleBrandId"
}
})
}
brandId: "exampleBrandId" - this should be dynamic, and one of the options could be something like "All Brands", which would then query all brands.

Resources