Graphql don't map data from resolve function in to the server answer - graphql-js

I have express server with running GraphQL on it.
There is a schema with Foo type
FooType = new GraphQLObjectType({
name: 'Foo',
fields: () => ({
name: {
type: GraphQLString,
},
surname: {
type: GraphQLString,
},
}),
});
schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
foo: {
type: FooType,
resolve: () => fooResolver
}
}
})
})
Resolver for foo returns object { name: 'bar', surname: 'boo' }, but in response from graphQL server I got an object { name: 'bar', surname: null }
The question is -
Why could it be and how could it be possible?
I thought GraphQL just maps the result object from resolver into
response object, doesn't it?

Related

Recursive mongoose schema does not result in correct object stores

I have a recursive model schema defined in a schema which uses the add() method in the Schema class to incrementally build the schema. It seems to build the paths correctly as shown when I print out the paths. However, when I use the Model defined to store the object in the database, it is missing the inner BNode. Here is a definition of the schema:
import mongoose from 'mongoose';
const BNodeSchema = new mongoose.Schema({
bValue: { type: [Number] },
id: String,
})
const RValue = {
rId: String,
value: Number
}
const ANodeSchema = new mongoose.Schema({
type: {
id: String,
rValues: {
type: Map,
of: RValue
},
}
})
const QuestSchema = new mongoose.Schema({
type: {
_id: { type: String, },
aNode: ANodeSchema,
bNodes: [BNodeSchema],
url: {
type: String
},
id: {
type: String
}
},
},
{ id: false }
)
ANodeSchema.add({ quest: QuestSchema });
const QuestNodeSchema = new mongoose.Schema({
_id: { type: String, unique: true },
quests: { type: [QuestSchema] },
}, {
id: false
})
export const QuestModel = mongoose.model('QuestModel', QuestNodeSchema);
QuestNodeSchema.eachPath(function(path:any) {
console.log(path);
});
{
_id: 12223,
quests:[
{
id: 'Quest-111-111' ,
aNode: {
id: 'A222222',
rValues: {
rId: 'RR1222',
value: 44422
},
quest:{
url: 'https://deptio-opcom',
id: '22222-QST',
bNodes:[{
bValue: 'B22190',
value: 22085
}]
}
}
}
]
}
I have included a sample of the json I am storing in the database. I use a class, not included for brevity to create the equivalent JSON object in the final format to be stored. My feeling is that there is something not quite right with my schema definition. I would be most grateful if someone could help me figure out what I am missing in my definition. Thanks a lot

How to define array type for multiple or nested json data from REST API

I'm new to GraphQL thingy. I have a problem in fetching array data from API using express-graphql server and I find to hard the solution somewhere. Here is the scenario.
I have a GET data from REST API which has the response that similar like this :
{
"id": 1,
"name": "billy",
"foods": [
{
"food":{
"name":"crepes",
"taste": "crunchy"
}
},
{
"food":{
"name":"noodle",
"taste":"spicy"
}
},
]
}
In my schema, I have successfully gets the id and name which I implement like this :
const FoodsType= new GraphQLObjectType({
name: 'foods',
fields: () => ({
id:{ type: GraphQLInt },
name:{ type: GraphQLString},
foods: { type: GraphQLArray}
})
});
As you can see I with my code above, I failed fetching foods data which contains array data because there is no scalar type like GraphQLArray.
My question is how do we get the foods data with containing multiple json data food inside it ?
const ResType= new GraphQLObjectType({
name: 'response',
field:() => ({
name: {type: GraphQLString},
taste: {type: GraphQLString}
})
});
const FoodsType= new GraphQLObjectType({
name: 'foods',
fields: () => ({
id:{ type: GraphQLInt },
name:{ type: GraphQLString},
foods: { type: new GraphQLList(ResType)}
})
});
After some attempt, I finally manage to solve this by define the types of every depth level. Here is my answer for schema file.
const FoodsType = new GraphQLObjectType({
name: 'foods',
fields: () => ({
id:{ type: GraphQLInt },
name: { type: GraphQLString },
foods:{ type: new GraphQLList(FoodType) }
})
});
const FoodType = new GraphQLObjectType({
name: 'food',
fields: () => ({
food: {type: FoodDetail}
})
});
const FoodDetail = new GraphQLObjectType({
name: 'fooddetail',
fields: () => ({
name:{ type: GraphQLString },
taste:{ type: GraphQLString}
})
});
And here is the resolver that I get from API
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
foods: {
type: FoodsType,
args: {
id: { type: GraphQLInt }
},
resolve(parent, args) {
return axios
.get(`https://hereisanapi/${args.id}`)
.then(res => {
return res.data;
});
}
}
}
});
Then in GraphQL Query I put this.
{
foods(id:1){
food{
name,
taste
}
}
}

How to rollback mongodb using mongoose

I have an array as below.
const array =
[
{ name: 'Tom',
age: '30'
},
{ name: 'Sam',
age: '24'
}
]
And I create this array using mongoose.
Schema.create(array)
'name' and 'age' are required. Therefore in this case, they are created well.
But When I put this array,
const array =
[
{ name: 'Tom',
age: '30'
},
{ name: 'Sam'}
]
Tom is created but Sam is not created as it doesn' t have age value.
When one of those has an error during create, I want to not save nothing at all.
It's becuase 'front client' have to try insert again when receiving error response.
How can I control transaction using mongo and mongoose? Thank you for reading it.
You can create a Schema model for that and add required to it :
var mongoose = require('mongoose')
const Schema = mongoose.Schema
const myUserSchema = new Schema ({
users : [{
name: {
type: String,
required: true
},
age: {
type: String,
required: true
}
}]
})
var myUser = mongoose.model('myUser', myUserSchema)
Then:
const array =
[
{ name: 'Tom',
age: '30'
},
{ name: 'Sam'}
]
const newUser = new myUser({
users: array
})
newUser.save((err, user)=>{
if (err) {
console.log(err)
}
})
It should validate your array at the time when you try to save it and throw an error in case if something is missing.
Example of thrown error:
ValidationError: myUser validation failed: users.1.age: Path `age` is required

Graphql create relations between two queries.Error cannot access before initialization

I have this code:
const ProductType = new GraphQLObjectType({
name: 'Product',
fields: {
id: { type: GraphQLID },
name: { type: GraphQLString },
category: {
type: CategoryType,
resolve: async (parent) => {
return await Category.findOne({_id: parent.category});
}
}
}
});
const CategoryType = new GraphQLObjectType({
name: 'Category',
fields: {
id: { type: GraphQLID },
name: { type: GraphQLString },
products: {
type: ProductType,
resolve: async (parent, args) => {
return await Product.find({category: parent._id});
}
}
}
});
const Query = new GraphQLObjectType({
name: 'Query',
fields: {
Categories: {
type: new GraphQLList(CategoryType),
resolve: async () => {
return await Category.find();
}
}
}
});
When i try to compile i get ReferenceError: Cannot access 'CategoryType' before initialization.
I understand that first of all I should declare and only after that use, but I saw a similar code in one lesson on YouTube, and I think that it should work, but it’s not.
fields can take a function instead of an object. This way the code inside the function won't be evaluated immediately:
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
category: {
type: CategoryType,
resolve: (parent) => Category.findOne({_id: parent.category}),
}
})

GraphQL Schema for mongoose Mixed type (Schema.Types.Mixed)

I have a Mongoose schema with the following structure:
import mongoose from 'mongoose';
const PropertySchema = new mongoose.Schema({
name: {
type: String
},
description: {
type: String
},
value: {
type: mongoose.Schema.Types.Mixed
},
unit: {
type: String
},
});
export default mongoose.model('Property', PropertySchema);
I need to build a GraphQL query for the given data. How do I handle the Mixed type for the value property ?
Here is my try:
import NodeInterface from '../interfaces';
import PropertyModel from '../../models/Property';
const fields = {
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: (obj) => dbIdToNodeId(obj._id, "Property")
},
name: {
type: GraphQLString
},
description: {
type: GraphQLString
},
value: {
type: <<< What to use here ?
},
unit: {
type: GraphQLString
}
};
export const PropertyType = new GraphQLObjectType({
name: 'Property',
description: 'Property',
interfaces: () => [NodeInterface],
isTypeOf: (value) => value instanceof PropertyModel,
fields: fields
});