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

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
});

Related

How to I resolve below graphql query in mongodb nested array

my model schema look like this
const mongoose = require("mongoose")
const userSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
select: false,
},
email: {
type: String,
required: true,
unique: true,
match: [
/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/,
"Please enter a valid email",
],
},
followers:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"user"
}
],
following:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"user"
}
],
displayName: {
type: String,
required: false,
},
},
{ timestamps: true }
)
module.exports = mongoose.model("user", userSchema)
in this schema all working good like mutation work fine but when i fetch query of all user then in that query followers and following field return null like bellow image
and my graphql query is
const users = {
type: new GraphQLList(UserType),
description: "Retrieves list of users",
resolve(parent, args) {
return User.find()
},
}
and typedef is
const UserType = new GraphQLObjectType({
name: "User",
description: "User types",
fields: () => ({
id: { type: GraphQLID },
username: { type: GraphQLString },
email: { type: GraphQLString },
post:{
type: GraphQLList(PostType),
resolve(parent, args) {
return Post.find({ authorId: parent.id })
},
},
savePost:{
type:GraphQLList(savedPosts1),
resolve(parent, args) {
return SavePost.findById({ authorId: parent.id })
},
},
followers:{
type:GraphQLList(UserType),
},
following:{
type:GraphQLList(UserType)
}
// displayName: { type: GraphQLString },
}),
})
so please tell me how to i resolve that followers and following query in graphql with mongodb and tell me what i write in my userType typedef

MissingSchemaError: Schema hasn't been registered for model "Product"

------------------------------
Here is Order Controller
-----------------------------
import nc from "next-connect";
import db from "../../../utils/db";
import Order from "../../../models/OrderModel";
import { isAuth } from "../../../utils/auth";
const handler = nc();
handler.use(isAuth);
handler.get(async (req, res) => {
try {
await db.connect();
const order = await Order.findById(req.body.order).populate({
path: "product",
model: "Product",
});
await db.disconnect();
res.send(order);
} catch (err) {
console.log(err);
}
});
export default handler;
--------------------------------------------------------------
Here is Order Schema
--------------------------------------------------------------
import mongoose from "mongoose";
const orderSchema = new mongoose.Schema(
{
product: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Product",
required: true,
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
}
},
{ timestamps: true }
);
const Order = mongoose.models.Order || mongoose.model("Order", orderSchema);
export default Order;
----------------------------
Here is Product Schema
----------------------------
import mongoose from "mongoose";
const productSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
category: {
type: String,
required: true,
},
period: {
type: String,
required: true,
},
features: [{ type: String, required: true }],
},
{ timestamps: true }
);
const Product =
mongoose.models.Product || mongoose.model("Product", productSchema);
export default Product;
--------------------
I am getting this error: "MissingSchemaError: Schema hasn't been registered for model "Product".
Use mongoose.model(name, schema)"
There are also some orders including product ObjectId and I am trying to get the data using populate on the POSTMAN but getting this error.
I've really searched much before posting this but I've didn't solve the error

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
}
}
}

Why graphql type relations returns null values?

i have this schema.js of SHIPS
// Ships
const ShipType = new GraphQLObjectType({
name: "Ships",
fields: () => ({
ship_id: { type: GraphQLString },
ship_name: { type: GraphQLString },
home_port: { type: GraphQLString },
ship_type: { type: GraphQLString },
year_built: { type: GraphQLInt },
position: { type: ShipPositionType },
active: { type: GraphQLBoolean }
})
})
// Ship positions
const ShipPositionType = new GraphQLObjectType({
name: "ShipPositions",
fields: () => ({
latitude: { type: GraphQLFloat },
longitude: { type: GraphQLFloat }
})
});
at ShipType i have added a new field "position" which will return ShipPositionType
this is what i return so far
// get ships
ships: {
type: new GraphQLList(ShipType),
resolve(parent, args) {
return axios.get('https://api.spacexdata.com/v3/ships')
.then(res => res.data);
}
}
The position field inside the shipType need to have a resolver, inside the resolver you return the ship data based on the ShipType ship_id matching the ShipPositionType ship_id. i.e(return data.find(ship => ship.shid_id === parent.ship_id )) . So first add a ship_id field to the ShipPositionType Object.
Something like this
// Ships
const ShipType = new GraphQLObjectType({
name: "Ships",
fields: () => ({
ship_id: { type: GraphQLString },
ship_name: { type: GraphQLString },
home_port: { type: GraphQLString },
ship_type: { type: GraphQLString },
year_built: { type: GraphQLInt },
position: {
type: ShipPositionType,
resolve(parent,args) {
return data.find(data => data.ship_id === parent.ship_id)}
},
active: { type: GraphQLBoolean }
})
})
//You need to add a ship_id field here too
// Ship positions
const ShipPositionType = new GraphQLObjectType({
name: "ShipPositions",
fields: () => ({
ship_id: {type: {GraphQLString},
latitude: { type: GraphQLFloat },
longitude: { type: GraphQLFloat }
})
});

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}),
}
})