How do I make a schema for an object property that is an array of strings in GraphQL? I want the response to look like this:
{
name: "colors",
keys: ["red", "blue"]
}
Here is my Schema
var keysType = new graphql.GraphQLObjectType({
name: 'keys',
fields: function() {
key: { type: graphql.GraphQLString }
}
});
var ColorType = new graphql.GraphQLObjectType({
name: 'colors',
fields: function() {
return {
name: { type: graphql.GraphQLString },
keys: { type: new graphql.GraphQLList(keysType)
};
}
});
When I run this query I get an error and no data, the error is just [{}]
query { colors { name, keys } }
However when I run a query to return just the name I get a successful response.
query { colors { name } }
How do I create a schema that returns an array of strings for when I query for keys?
I figured out the answer. The key is to pass the graphql.GraphQLString into graphql.GraphQLList()
The schema becomes:
var ColorType = new graphql.GraphQLObjectType({
name: 'colors',
fields: function() {
return {
name: { type: graphql.GraphQLString },
keys: { type: new graphql.GraphQLList(graphql.GraphQLString)
};
}
});
Using this query:
query { colors { name, keys } }
I get the desired results:
{
name: "colors",
keys: ["red", "blue"]
}
Related
let object=
[
{
id:`01`,
name:`fish`,
type:null,
care:'owner',
},
{
id:`02`,
name:`fish`,
type:'fresh',
care:'peter',
},
{
id:`03`,
name:`fish`,
type:`fresh`,
care:'amy',
},
{
id:`04`,
name:`fish`,
type:`tank`,
care:'abc',
},
{
id:`05`,
name:`animal`,
type:`pet`,
care:'teen',
},,
{
id:`06`,
name:`animal`,
type:`pet`,
care:'ran',
},
{
id:`07`,
name:`animal`,
type:null,
care:'roh',
},
{
id:`08`,
name:`food`,
type:`veg`,
care:'test',
},
{
id:`09`,
name:`food`,
type:null,
care:'dop',
}
]
object.map((value)=>{
console.log(value.name)
// i am calling function here by passing value.name as a parameter
let gotValue = functionName(value.name);
// using type also
if(typeof value.type!=="string"){
// Do some task here with gotValue
}
})
I have this object and i am getting some value from it for ex getting name from it as i want to pass this name to function but the problem is due to repeat of data the function calling again and again is there any possibility i can run function inside map but with unique value any help ?
as my output is getting like this
fish
fish
fish
animal
animal
animal
and this value.name is passing inside my function so its repeating like this
functionName(fish);
functionName(fish);
functionName(fish);
functionName(animal);
functionName(animal);
functionName(animal);
multiple time function is running with same name and getting duplicate values
just need my function run with unique name
functionName(fish)
functionName(animal);
functionName(food);
as i want to stay inside map function because i am performing some task which can only be possible inside map that's why i need unique value
You can use Set which can be used to test if the object with value already exists or not. It will only call the function only once.
let object = [
{
id: `01`,
name: `fish`,
type: null,
},
{
id: `02`,
name: `fish`,
type: `fresh`,
},
{
id: `03`,
name: `fish`,
type: `tank`,
},
{
id: `04`,
name: `animal`,
type: `pet`,
},
{
id: `05`,
name: `animal`,
type: `wild`,
},
{
id: `06`,
name: `animal`,
type: null,
},
{
id: `07`,
name: `food`,
type: `veg`,
},
{
id: `08`,
name: `food`,
type: null,
},
];
const dict = new Set();
object.map((value) => {
if (!dict.has(value.name)) { // Run only if objet with name is not already existed in dict
dict.add(value.name);
console.log(value.name); // For testing
// functionName(value.name);
}
});
If you want to call the function with two filters then you can use some to find the elements in an array. See I've now declared dict as an array
let object = [{
id: `01`,
name: `fish`,
type: null,
},
{
id: `02`,
name: `fish`,
type: `fresh`,
},
{
id: `03`,
name: `fish`,
type: `tank`,
},
{
id: `04`,
name: `animal`,
type: `pet`,
},
{
id: `05`,
name: `animal`,
type: `wild`,
},
{
id: `06`,
name: `animal`,
type: null,
},
{
id: `07`,
name: `food`,
type: `veg`,
},
{
id: `08`,
name: `food`,
type: null,
},
{
id: `09`,
name: `food`,
type: null,
},
{
id: `10`,
name: `fish`,
type: `tank`,
},
];
const dict = [];
object.map((value) => {
const { name, type } = value;
if (!dict.some((obj) => obj.name === name && obj.type === type)) {
// Run only if objet with name is not already existed in dict
dict.push({ name, type });
console.log(name, type); // For testing
// functionName(value.name);
}
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think I am missing something in the docs but I am not sure how to handle objects as the type withing a new GraphQLObjectType. I am looking to set up the queries for weather data from this sample data, and I am not sure how to handle the nested objects. I currently have:
// Creating a Type for the Weather Object
const WeatherType = new GraphQLObjectType({
name: 'Weather',
fields: () => ({
weather: { type: GraphQLObject? },
})
});
I am looking to get specific with the queries and set up the structure to specify more select data like:
// Creating a Type for the Weather Object
const WeatherType = new GraphQLObjectType({
name: 'Weather',
fields: () => ({
weather: {
main: { type: GraphQLString },
// And so on
},
})
});
Are there any references to examples of this?
When constructing a schema with nested custom types, you just set the type of the field to a reference of your other created type:
const WeatherType = new GraphQLObjectType({
name: 'Weather',
fields: {
id: {
type: GraphQLInt,
}
main: {
type: GraphQLString,
}
description: {
type: GraphQLString,
}
icon: {
type: GraphQLString,
}
}
})
const MainType = new GraphQLObjectType({
name: 'Main',
fields: {
temp: {
type: GraphQLFloat,
}
pressure: {
type: GraphQLFloat,
}
humidity: {
type: GraphQLFloat,
}
tempMin: {
type: GraphQLFloat,
resolve: (obj) => obj.temp_min
}
tempMax: {
type: GraphQLFloat,
resolve: (obj) => obj.temp_max
}
}
})
const WeatherSummaryType = new GraphQLObjectType({
name: 'WeatherSummary',
fields: {
weather: {
type: new GraphQLList(WeatherType),
}
main: {
type: MainType,
}
}
})
Be careful when molding existing JSON responses into GraphQL schemas -- it's easy to get burned by differences in structure. For example, the main field in your sample response is an object, but the weather field is actually an array, so we have to wrap it in GraphQLList when specifying the type for the field.
I have been writing an API that uses GraphQL. I am still pretty new to it, and have been running into some problems regarding mutations. A simplistic form of my API has two record types. There is a contact record and a tag record. A contact record can have multiple tag records associated with it.
The schema I wrote for each of these record types are below:
const Tag = new graphQL.GraphQLObjectType({
name: 'Tag',
description: 'Categorizes records into meaningful groups',
fields: () => ({
_id: {
type: graphQL.GraphQLID
},
name: {
type: graphQL.GraphQLString
}
})
});
const Contact = new graphQL.GraphQLObjectType({
name: 'Contact',
description: 'Contact record',
fields: () => ({
_id: {
type: graphQL.GraphQLID
},
name: {
type: graphQL.GraphQLString
},
tags: {
type: new graphQL.GraphQLList(Tag),
resolve: function(src, args, context) {
return TagModel.findByContactId(src._id)
.then(tags => {
return Promise.map(tags, (tag) => {
return TagModel.findById(tag.tag_id);
});
});
}
}
})
});
I can make a mutation easy enough on records such as tags since they don't contain nested records of their own, but I'm not sure how to make a mutation on a record like contacts since it can contain tags as well. The mutation code I put in place looks like this:
const Mutation = new graphQL.GraphQLObjectType({
name: 'Mutation',
fields: {
createContact: {
type: Contact,
description: "Create Contact",
args: {
name: {type: new graphQL.GraphQLNonNull(graphQL.GraphQLString)},
tags: {type: new graphQL.GraphQLList(Tag)}
},
resolve: function(source, args) {
return ContactModel.save(args.name);
}
}
}
});
I'm not sure how to complete the resolver in the mutation in order to be able to save a contact and tag records at the same time. For instance, if I made a mutation query to save a new contact record with a new tag like this:
{"query": "mutation createNewContact {
contact: createContact (name: "John Smith", tags { name: "family" } )
{_id, text, tags { name } } }" }
Is there something special that I need to do in my mutation schema in order to allow for this type of mutation to happen?
You can't use Tag as an input object type, you would have to create a type like TagInput
const TagInput = new GraphQLInputObjectType({
name: 'TagInput',
fields: {
_id: { type: GraphQLID },
name: { type: GraphQLString }
}
});
It is recommended to always create Input version of your normal type. You could do the same with Contact by creating ContactInput. Then you could create a mutation in very similar way you did it
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
createContact: {
type: Contact,
args: {
contact: { type: new GraphQLNonNull(ContactInput) },
tags: { type: new GraphQLList(TagInput) }
},
resolve: (root, args, context) => {
console.log(args);
// this would console something like
// { contact: { name: 'contact name' },
// tags: [ { name: 'tag#1' }, { name: 'tag#2' } ] }
// here create contact with tags
}
}
});
The query you would run would look like that
{
"operationName": "createContact",
"query": "mutation createContact($contact: ContactInput!, $tags: [TagInput])
{
createContact(contact: $contact, tags: $tags) {
_id
text
tags {
name
}
}
}",
"variables": {
contact: { name: "contact name" },
tags: [ { name: "tag#1" }, { name: "tag#2" } ]
}
}
I want to use mutation in Relay to change an array (not connection). The array is typed GraphQLList in the GraphQL side. The graphql side worked perfectly, but relay side needs dataID for each item in an array. And when I am inserting new item or modifying existing item in the array, there are no dataID provided? What is the right way to do this? By the way, I am using redux to maintain the list, and submit changes via relay at the end.
The schema:
let widgetType = new GraphQLInputObjectType({
name: 'Widget',
fields: () => ({
label: {
type: GraphQLString
},
type: {
type: GraphQLString
},
list: {
type: new GraphQLList(GraphQLString)
},
description: {
type: GraphQLString
},
required: {
type: GraphQLBoolean
}
})
});
let modifyFormMutation = mutationWithClientMutationId({
name: 'ModifyForm',
inputFields: {
id: {
type: new GraphQLNonNull(GraphQLString)
},
name: {
type: new GraphQLNonNull(GraphQLString)
},
userId: {
type: new GraphQLNonNull(GraphQLString)
},
widgets: {
type: new GraphQLList(widgetType)
}
},
outputFields: {
formEdge: {
type: formConnection.edgeType,
resolve: (obj) => {
return {
node: {
id: obj.id,
name: obj.name,
userId: obj.userId,
widgets: obj.widgets
},
cursor: obj.id
};
}
},
app: {
type: appType,
resolve: () => app
}
},
mutateAndGetPayload: ({
id, name, userId, widgets
}) => {
db.collection('forms').findOneAndUpdate({
_id: new ObjectID(id)
}, {
name, userId, widgets, createAt: Date.now()
});
return {
id, name, userId, widgets
};
}
})
Relay mutation:
export default class ModifyFormMutation extends Mutation {
getMutation () {
return Relay.QL`mutation{modifyForm}`;
}
getFatQuery() {
return Relay.QL`
fragment on ModifyFormPayload {
formEdge
app { forms }
}
`;
}
getCollisionKey() {
return `check_${this.props.app.id}`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
formEdge: {node: this.props.node},
app: this.props.app.id
}
}];
}
getVariables() {
return {
name: this.props.node.name,
id: this.props.node.id,
userId: this.props.node.userId,
widgets: this.props.node.widgets
};
}
getOptimisticResponse() {
return {
formEdge: {
name: this.props.node.name,
id: this.props.node.id,
userId: this.props.node.userId,
widgets: this.props.node.widgets
}
};
}
}
And error message from browser:
"Variable "$input_0" got invalid value
{"name":"asdfasdfsa","id":"57e790cec252f32aa805e38d","userId":"57e10a02da7e1116c0906e40","widgets":[{"dataID":"client:618507132","label":"sdfas","type":"text","list":[],"description":"","required":true},{"label":"sfasdfasaaa","list":[],"type":"number","description":"","required":"false"}],"clientMutationId":"0"}.↵In
field "widgets": In element #0: In field "dataID": Unknown field."
I am new to MongoDB, I am using Node.js, Express 4 and mongoose(mongoDB) for my project.I stuck to save form data to mongoDB within loop and my model contains Objects and array of objects as well.
Model :
var Subscriber = new Schema({
first_name: String,
emergency_contact_1: {
name: String,
number: [{
type: String
}]
},
residential: {
phone: String,
address: String,
...
},
medications: [
{
visit_id: { type: Object },
name: String,
....
}],
food_allergies: [
{type: String}
],
....
});
Controller :
I want to save data in this way:
var subscriber = new Subscriber();
//Here I am trying to save all form's fields to mongoBD fields.
for (var field in form_data) {
subscriber[field] = form_data[field];
}
subscriber.save(function (err1, instance) {
if (err) {
console.log("error");
return res.send("...");
}
console.log("saved successfully");
}
Normal fields are getting saved properly using above loop but when objects or arrays came then it won't get save to mongoDB.
Any solution ? or any other way to insert/save data through loop to mongoDB model ?
Any help would be appreciated.Thank you..!!
Nodejs
var PersonSchema = new Schema({
name: {
given: {
type: String,
required: true
},
family: {
type: String,
required: true
}
},
children: [PersonSchema]
});
var Person = mongoose.model('Person', PersonSchema);
app.post('/person', function (req, res) {
Person.create(req.body)
.then(function (created) {
console.log(created);
res.json(created.id);
});
});
Client
$.ajax({
url: '/person',
type: 'POST',
data: {
name: {
family: 'Green'
},
children: [{
name: {
given: 'Matt',
family: 'Green'
}
}, {
name: {
given: 'Dave',
family: 'Green'
}
}]
}
})
As you can see, I have nested objects and arrays. This works fine for me :)