I have a GraphQL userType and EventType and on my userType I have to make a nested query using EventType but I also need to return user information. Since EventType doesn't have fields same as user info so to pass my code on testing I had to manually copy-paste UserType to EventType but I don't want this to solution.
Is there a way to like merge types? I'm using MongoDB as my database so when trying to do a POPULATE the user info comes back but GraphQL making it hard.
So this is what I did on EventType to pass the test. Under "fixme" I copy the UserType:
module.exports = {
EventType: new GraphQLObjectType({
name: 'Event',
fields: () => ({
id: {type: GraphQLID},
organizerId: {type: new GraphQLList(GraphQLID)},
title: {type: GraphQLString},
image: {type: GraphQLString},
description: {type: GraphQLString},
location: {type: GraphQLString},
items: {type: GraphQLInt},
date: {type: GraphQLString},
attendeesId: {type: new GraphQLList(GraphQLID)},
supplies: {type: new GraphQLList(GraphQLString)},
test: {type: GraphQLString},
// FIXME: USER TYPES!
firstName: {type: GraphQLString},
lastName: {type: GraphQLString},
email: {type: GraphQLString},
age: {type: GraphQLInt},
token: {type: GraphQLString},
image: {type: GraphQLString},
phone: {type: GraphQLInt},
address: {type: GraphQLString},
// ! TYPE RELATION
userRelatedToEvent: {
type: UserType,
resolve: async (parent, args) => {
const id = {
id: parent.organizerId
};
return await getCurrentUser(id);
}
}
})
})
};
this is my code on UserType that is doing a Type relation on EventType see resolve prop
module.exports = {
UserType: new GraphQLObjectType({
name: 'User',
fields: () => ({
id: {type: GraphQLID},
firstName: {type: GraphQLString},
lastName: {type: GraphQLString},
email: {type: GraphQLString},
age: {type: GraphQLInt},
token: {type: GraphQLString},
image: {type: GraphQLString},
phone: {type: GraphQLInt},
address: {type: GraphQLString},
eventsId: {type: new GraphQLList(GraphQLID)}, // <-- this will be the query for userRelatedToUser
statusCode: {type: GraphQLInt},
isSuccess: {type: GraphQLBoolean},
msg: {type: GraphQLString},
test: {type: GraphQLString}, // testing query
// errors: { type: GraphQ LString },
eventRelatedToUser: {
type: require('./eventTypeDef').EventType,
resolve: async (parent, args) => {
const event = {
event: parent.eventsId
};
const test = await getEventWithEventId(event); // <-- queries event
const id = {
id: test.attendeesId
};
const users = await getCurrentUser(id); // <-- user info
console.log(users);
return {...users, ...test};
}
}
})
})
};
Related
In my mongodb model, name is required but i want to make it optional in graphql. How can i do this?
updateExercise: {
type: ExerciseType,
args: {
id: {type: new GraphQLNonNull(GraphQLString)},
username: {type: new GraphQLString},
description: {type: new GraphQLString},
duration: {type: new GraphQLInt},
date: {type: new GraphQLString}
},
resolve(parent, args) {
Exercise.findByIdAndUpdate(args.id)
.then(exercise => {
exercise.username = args.username,
exercise.description = args.description,
exercise.duration = args.duration,
exercise.date = args.date
exercise.save()
.then( () => 'Succesfully Updated')
.catch( e => console.log(e) )
})
}
}
You are misusing the findByIdAndUpdate function. It should probably be used in this way:
const SomeType = new GraphQLObjectType({
updateExercise: {
type: ExerciseType,
args: {
id: {type: new GraphQLNonNull(GraphQLString)},
username: {type: GraphQLString},
description: {type: GraphQLString},
duration: {type: GraphQLInt},
date: {type: GraphQLString}
},
resolve(parent, args) {
return Exercise.findByIdAndUpdate(args.id, {
username: args.username || undefined,
description: args.description,
duration: args.duration,
date: args.date
}).then(() => 'Succesfully Updated')
.catch(e => console.log(e))
})
}
}
});
We use a little trick in JS to short-circuit the returned value. This will supply undefined for the username property when args.username is null. If you are in an environment where you are not sure if undefined as been reassigned you can use void 0 instead. If you are using a new TypeScript or EcmaScript version you can use the newer ?? operator instead of ||.
I am getting a response from an Api that looks like this:
property: Array(100)
0: {identifier: {…}, address: {…}, location: {…}, vintage: {…}}
1: {identifier: {…}, address: {…}, location: {…}, vintage: {…}}
2: {identifier: {…}, address: {…}, location: {…}, vintage: {…}}
3: {identifier: {…}, address: {…}, location: {…}, vintage: {…}}
I am wanting a list of some specified fields in the address object for instance just country and oneLine, but for every index of the property
array
address:
country: "US"
countrySubd: "CA"
line1: "1702 ELKHORN RD"
line2: "ROYAL OAKS, CA 95076"
locality: "Royal Oaks"
matchCode: "ExaStr"
oneLine: "1702 ELKHORN RD, ROYAL OAKS, CA 95076"
postal1: "95076"
postal2: "9218"
postal3: "R002"
I have been struggling for 2 days on how to write the schema for this in my graphql schema page. Can somebody please help me?
here is what I have been trying but keep getting null value for data
require("es6-promise").polyfill();
require("isomorphic-fetch");
const {
GraphQLString,
GraphQLList,
GraphQLSchema,
GraphQLObjectType,
GraphQLInt
} = require("graphql");
const Identifier = new GraphQLObjectType({
name: "identifier",
fields: () => ({
obPropId: { type: GraphQLInt }
})
});
const AddressType = new GraphQLObjectType({
name: 'Address',
fields: () => ({
country: { type: GraphQLString },
oneLine: {type: GraphQLString }
})
})
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
property: {
type: new GraphQLList(Identifier),
resolve(parent, args) {
return fetch(
"https://api.gateway.attomdata.com/propertyapi/v1.0.0/property/address?postalcode=95076&page=1&pagesize=100",
{
headers: {
Accept: "application/json",
APIKey: "XXXXXXXXXXXXXXXXXXXX"
}
}
)
.then((response) => {
const jsonResponse = response.json();
return jsonResponse
}).then((jsonResonse) => console.log(JSON.stringify(jsonResonse)))
.then(res => res.data)
.catch(error => {
console.log(error);
});
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery
});
Im running it on a express server and do my checks on localhost:5000/graphql
In the comments we were able to work out the following:
Another type is required to connect the Address type with the RootQuery type. We can introduce the type and adjust the return type of the query type:
type Property {
id: Identifier
address: Address
}
type Query {
property: [Property] # consider using plural field name "properties"
}
I created a working Codesandboy to show how it behaves.
I am writing a mutation for a GraphQL schema:
const Schema = new GraphQLSchema({
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: () => ({
person: {
type: GraphQLString,
args: {
name: {type: GraphQLString},
school: {type: GraphQLString},
},
resolve: mutatePerson,
},
}),
}),
});
I want to ensure that mutatePerson will only work if both name and school arguments are present. How can I check that?
The GraphQLNonNull type wrapper is used to specify both fields and arguments as non-null. For fields, that means the value of the field in the query results cannot be null. For arguments, that means that the argument cannot be left out or have a value of null. So your code just needs to look more like this:
args: {
name: {
type: new GraphQLNonNull(GraphQLString),
},
school: {
type: new GraphQLNonNull(GraphQLString),
},
},
it is better to do it as follow (in the model) if you want to reject empty Strings like "", it is different from Null, this way you can reject both Null and empty "".
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const buinessSchema = new Schema({
name: { type: String, required: true, unique: true },
address: { type: String, required: true },
phone: { type: String, required: true },
email: { type: String, required: true },
website: { type: String, required: true },
currency: { type: String, required: true },
aboutus: { type: String, required: true },
terms: String,
slogan: String,
logo: { type: String, required: true }
});
module.exports = mongoose.model("Buiness", buinessSchema);
I am new to graphql, I was creating following schema with graphql
// promotion type
const PromoType = new GraphQLObjectType({
name: 'Promo',
description: 'Promo object',
fields: () => ({
id: {
type: GraphQLID,
description: 'id of the promo'
},
title: {
type: GraphQLString,
description: 'this is just a test'
},
departments: {
type: new GraphQLList(DepartmentType),
description: 'departments associated with the promo'
}
})
})
and department type
// department type
const DepartmentType = new GraphQLObjectType({
name: 'Department',
description: 'Department object',
fields: () => ({
id: {
type: GraphQLID,
description: 'id of the department'
},
name: {
type: GraphQLString,
description: 'name of the department'
},
createdAt: {
type: GraphQLDate,
description: 'date the promo is created'
},
updatedAt: {
type: GraphQLDate,
description: 'date the promo is last updated'
}
})
});
and the following are the resolvers
// Promos resolver
const promos = {
type: new GraphQLList(PromoType),
resolve: (_, args, context) => {
let promos = getPromos()
let departments = getDepartmentsById(promos.promoId)
return merge(promos, departments)
}
};
//Departments resolver
const departments = {
type: new GraphQLList(DepartmentType),
args: {
promoId: {
type: GraphQLID
}
},
resolve: (_, args, context) => {
return getDepartmentsById(args.promoId)
}
};
the problem is I want to use the resolver of the departments into the resolver of the promos to get the departments.
I might be missing something obvious but is there any way to do this?
This is the way to do it. You want to think of it as graphs, rather than just a single rest endpoint.
To get data for Promo, you need to do it similarly to how I did it here, but for the parent node, if that makes sense. So, in e.g. viewer's resolve you add the query for Promo.
const PromoType = new GraphQLObjectType({
name: 'Promo',
description: 'Promo object',
fields: () => ({
id: {
type: GraphQLID,
description: 'id of the promo',
},
title: {
type: GraphQLString,
description: 'this is just a test',
},
departments: {
type: new GraphQLList(DepartmentType),
description: 'departments associated with the promo',
resolve: (rootValue) => {
return getDepartmentsById(rootValue.promoId);
}
}
})
});
I'm trying to implement a very basic GraphQL interface in Node.js, but no matter what I do I can't seem to get the resolve method of my foo type to trigger. When I run the following code in a unit test it runs successfully, but I can see from the (lack of) console output that resolve wasn't called, and as a result I get an empty object back when I call graphql(FooSchema, query).
Can anyone more experienced with GraphQL suggest what I might be doing wrong? I'm completely baffled as to how the whole operation can even complete successfully if GraphQL can't find and call the method that is supposed to return the results ...
const fooType = new GraphQLInterfaceType({
name: `Foo`,
description: `A foo`,
fields: () => ({
id: {
description: `The foo's id`,
type: new GraphQLNonNull(GraphQLInt),
},
title: {
description: `The foo's title`,
type: new GraphQLNonNull(GraphQLString),
}
})
});
const queryType = new GraphQLObjectType({
fields: {
foo: {
args: {
id: {
description: 'ID of the foo',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, { id }) => {
console.log(12345);
return getFoo(id)
},
type: fooType,
}
},
name: 'Query',
});
export default new GraphQLSchema({
query: queryType,
types: [fooType],
});
// In test:
const query = `
foo {
title
}
`;
const result = graphql(FooSchema, query); // == {}
const fooType = new GraphQLInterfaceType({
name: `Foo`,
description: `A foo`,
fields: () => ({
id: {
description: `The foo's id`,
type: new GraphQLNonNull(GraphQLInt),
},
title: {
description: `The foo's title`,
type: new GraphQLNonNull(GraphQLString),
}
})
});
This is an interface type, however your consumer queryType never implements it. A quick solution should be to change it to this:
const fooType = new GraphQLObjectType({
name: `Foo`,
description: `A foo`,
fields: () => ({
id: {
description: `The foo's id`,
type: new GraphQLNonNull(GraphQLInt),
},
title: {
description: `The foo's title`,
type: new GraphQLNonNull(GraphQLString),
}
})
});
Here's an example that works for me:
const {
GraphQLNonNull,
GraphQLInt,
GraphQLString,
GraphQLObjectType,
GraphQLSchema,
graphql,
} = require('graphql');
const fooType = new GraphQLObjectType({
name: `Foo`,
description: `A foo`,
fields: () => ({
id: {
description: `The foo's id`,
type: new GraphQLNonNull(GraphQLInt),
},
title: {
description: `The foo's title`,
type: new GraphQLNonNull(GraphQLString),
},
}),
});
const queryType = new GraphQLObjectType({
fields: {
foo: {
args: {
id: {
description: 'ID of the foo',
type: new GraphQLNonNull(GraphQLString),
},
},
resolve: (root, { id }) => {
return { id, title: 'some-title' };
},
type: fooType,
},
},
name: 'Query',
});
const schema = new GraphQLSchema({
query: queryType,
types: [fooType],
});
graphql(schema, `{ foo (id:"123") { id, title } }`).then(console.log.bind(console));
This should print:
$ node test.js
{ data: { foo: { id: 123, title: 'some-title' } } }
Here's the docs on the InterfaceType: http://graphql.org/learn/schema/#interfaces