How to properly resolve query MySql using sequelize and Graphql - mysql

I am learning GraphQL and trying to get data from MySql tables via sequelize in the resolve function on GraphQL. I have a Clients table associated with a Pets Table, where Pets belong to Client.
Here is my code:
const PetsType = new GraphQLObjectType({
name: "Pet",
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString },
breed: { type: GraphQLString },
type: { type: GraphQLString },
ClientId: { type: GraphQLString },
Comments: {
type: CommentsType,
resolve(parentValue, args) {
return db.Comments;
}
}
})
});
const ClientType = new GraphQLObjectType({
name: "Client",
fields: () => ({
id: { type: GraphQLString },
lastName: { type: GraphQLString },
firstName: { type: GraphQLString },
primaryPhoneNumber: { type: GraphQLString },
cellphone: { type: GraphQLString },
workPhone: { type: GraphQLString },
email: { type: GraphQLString },
Pets: {
type: PetsType,
resolve(parentValue, args) {
return db.Pet.findOne({
where: { ClientId: parentValue.id }
});
}
}
})
});
Using findOne works for clients with only one pet or only returns the first pet of a client who owns more than one. However, some clients have more than one pet, so findOne() doesn't really solve my problem.
I've tried:
return db.Pet.findAll({
where: { ClientId: parentValue.id }
});
But it returns the client with the fields on Pets null.
Here are my Sequelize models for both, Clients and Pets:
Clients:
module.exports = function(sequelize, DataTypes) {
var Client = sequelize.define(
"Client",
{
lastName: {
type: DataTypes.TEXT,
allowNull: false,
len: [1]
},
firstName: {
type: DataTypes.TEXT,
allowNull: false,
len: [1]
},
primaryPhoneNumber: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
},
cellphone: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
},
workPhone: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
},
email: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
}
},
{
timestamps: false
}
);
Client.associate = function(models) {
// Associating Clients with Pets
// When a Client is deleted, also delete any associated Pets
Client.belongsTo(models.User);
Client.hasMany(models.Pet, {
onDelete: "cascade"
});
};
return Client;
};
Pets:
module.exports = function(sequelize, DataTypes) {
var Pet = sequelize.define(
"Pet",
{
name: {
type: DataTypes.TEXT,
allowNull: false,
len: [1]
},
breed: {
type: DataTypes.TEXT,
allowNull: false,
len: [1]
},
type: {
type: DataTypes.TEXT,
allowNull: true
}
},
{
timestamps: false
}
);
Pet.associate = function(models) {
Pet.belongsTo(models.Client);
Pet.hasMany(models.Comment, {
onDelete: "cascade"
});
};
return Pet;
};
How can I retreive all Pets that belong to this client?
Thanks in advance.

As Daniel Rearden suggested, I changed it to: type: new GraphQLList(PetsType) to return a list of objects

Related

How to define in my model an array of id from another table in mysql and sequelize

I create an api in express.js, node.js, mysql and sequelize.
I have two models : Custom fields and Customer Types
Here is my customer type model :
module.exports = (sequelize, DataTypes) => {
const CustomerType = sequelize.define("customerType", {
name: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.STRING,
allowNull: false
},
user_id: {
type: DataTypes.STRING,
allowNull: false
}
})
return CustomerType
}
And there is my custom fields model :
const customerType = require('./customerTypeModel')
module.exports = (sequelize, DataTypes) => {
const CustomField = sequelize.define("customField", {
customer_type_ids: [
{
type: DataTypes.INTEGER,
references: {
model: customerType,
key: "id"
}
}
],
user_id: {
type: DataTypes.STRING,
allowNull: false
},
system_name: {
type: DataTypes.STRING,
allowNull: true
},
title: {
type: DataTypes.STRING,
allowNull: true
},
type: {
type: DataTypes.STRING,
allowNull: true
},
required: {
type: DataTypes.BOOLEAN,
allowNull: true
},
})
return CustomField
}
I need to have in my customField table an array of id from the customerType table.
For exemple i need to get a json like this :
{
"id": 1
"customer_types_ids": [
{
"id": 1,
"name": "Customers",
"description": "Customers",
"user_id": "123456"
},
{
"id": 2,
"name": "Leads",
"description": "Leads",
"user_id": "123456"
}
],
"user_id": "123456",
"system_name": "firstname",
"title": "Firstname",
"type": "text",
"required": true
}
How should I structure my custom field Model to be able to have a json like this in return?
Thanks for your help !
I assume you're expecting a One-to-Many relationship between CustomField and CustomerType. In this case, CustomerType owns the relation, so there is a reference to CustomField in the relational table of CustomerType called customFieldId.
// customerType.js
module.exports = (sequelize, DataTypes) => {
const CustomerType = sequelize.define("customerType", {
name: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.STRING,
allowNull: false
},
user_id: {
type: DataTypes.STRING,
allowNull: false
}
});
return CustomerType;
}
// customField.js
module.exports = (sequelize, DataTypes) => {
const CustomField = sequelize.define("customField", {
user_id: {
type: DataTypes.STRING,
allowNull: false
},
system_name: {
type: DataTypes.STRING,
allowNull: true
},
title: {
type: DataTypes.STRING,
allowNull: true
},
type: {
type: DataTypes.STRING,
allowNull: true
},
required: {
type: DataTypes.BOOLEAN,
allowNull: true
},
});
return CustomField;
}
// db.js
...
const CustomerType = require("./customerType.js")(sequelize, Sequelize.DataTypes);
const CustomField = require("./customField.js")(sequelize, Sequelize.DataTypes);
CustomField.hasMany(CustomerType, { as: "customer_types_ids" });
CustomerType.belongsTo(CustomField, {
foreignKey: "id",
as: "customFieldId",
});
This should define two relational tables with a One-to-Many relationship. The following code can be used to load a CustomField with all its CustomerTypes.
CustomField.findByPk(id, { include: ["customer_types_ids"] });

GraphQL Mutation is not letting me add data to mysql table with non null violation error

I am using GraphQL, Sequelize, and MySql to add data to Clients Table. In the GraphQl Mutation, I do the following:
const db = require("./models");
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addClient: {
type: ClientType,
args: {
lastName: { type: new GraphQLNonNull(GraphQLString) },
firstName: { type: new GraphQLNonNull(GraphQLString) },
primaryPhoneNumber: { type: new GraphQLNonNull(GraphQLString) },
cellphone: { type: GraphQLString },
workPhone: { type: GraphQLString },
email: { type: GraphQLString },
UserId: { type: new GraphQLNonNull(GraphQLString) }
},
resolve(parentValue, args) {
let newClient = new db.Client({
lastName: args.lastName,
firstName: args.firstName,
primaryPhoneNumber: args.primaryPhoneNumber,
cellphone: args.cellphone,
workPhone: args.workPhone,
email: args.email,
UserId: args.UserId
});
console.log(newClient);
return db.Client.create(newClient);
}
}
}
});
But I receive this error back when testing it on GraphiQL:
{
"errors": [
{
"message": "notNull Violation: Client.lastName cannot be null,\nnotNull Violation:
Client.firstName cannot be null",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"addClient"
]
}
],
"data": {
"addClient": null
}
}
I believe this error comes from sequelize as in my Model I define some Non-Null fields:
module.exports = function(sequelize, DataTypes) {
var Client = sequelize.define(
"Client",
{
lastName: {
type: DataTypes.TEXT,
allowNull: false,
len: [1]
},
firstName: {
type: DataTypes.TEXT,
allowNull: false,
len: [1]
},
primaryPhoneNumber: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
},
cellphone: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
},
workPhone: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
},
email: {
type: DataTypes.TEXT,
allowNull: true,
len: [1]
}
},
{
timestamps: false
}
);
Client.associate = function(models) {
// Associating Clients with Pets
// When a Client is deleted, also delete any associated Pets
Client.belongsTo(models.User);
Client.hasMany(models.Pet, {
onDelete: "cascade"
});
};
return Client;
};
This is my query from the front end:
mutation {
addClient(lastName: "ali", firstName: "muhamed", primaryPhoneNumber:
"00990099009", email: "jalimaƱa#email.com", UserId: "14fb9610-4766-11ea-9a4e-
e130bc08c2aa") {
lastName,
firstName
}
}
Does anybody know why is this happening? Any help will be highly appreciated.
Model.create takes a plain object with the values the Model instance should be initialized with. You shouldn't pass an existing instance of Model to it. Instead, just call the save method on the instance.
const instance = new SomeModel({ firstName: 'Bob' })
await instance.save()
This is equivalent to
const instance = SomeModel.build({ firstName: 'Bob' })
await instance.save()
and
await SomeModel.create({ firstName: 'Bob' })

Can i use `SET` variable in sequelize in nodejs

Can i use SET variable in sequelize in nodejs?
Sequelize
Model
Session Model
"use strict";
module.exports = (sequelize, DataTypes) => {
const Sessions = sequelize.define(
"sessions",
{
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
challenge_id: {
type: DataTypes.INTEGER,
references: {
model: "challenges",
key: "id"
},
allowNull: false
},
createdAt: { type: DataTypes.DATE },
createdBy: {
type: DataTypes.INTEGER,
references: {
model: "users",
key: "id"
},
allowNull: false
},
showAtLeaderboard: { type: DataTypes.ENUM("yes", "no") },
sessionFile: { type: DataTypes.STRING },
score: { type: DataTypes.INTEGER },
},
{
timestamps: false,
underscored: true
}
);
return Sessions;
};
Challenge Model
"use strict";
module.exports = (sequelize, DataTypes) => {
const Challenges = sequelize.define(
"challenges",
{
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
song_id: { type: DataTypes.INTEGER },
challenge_name: { type: DataTypes.STRING },
challengeDescription: { type: DataTypes.STRING },
challengeImg: { type: DataTypes.STRING },
challengeType: { type: DataTypes.STRING },
coins: { type: DataTypes.INTEGER },
createdAt: { type: DataTypes.DATE },
expireAt: { type: DataTypes.DATE },
isActive: { type: DataTypes.ENUM("yes", "no") },
tags: { type: DataTypes.STRING }
},
{
timestamps: false,
underscored: true
}
);
return Challenges;
};
Relationship
db.challenges.hasMany(db.sessions, {
foreignKey: "challenge_id",
sourceKey: "id"
});
Can I perform below SQL query with sequelize Orm model?
SET #rank=0
SELECT `challenges`.`*`, `sessions`.*, #rank:=#rank+1 AS rank FROM `challenges` JOIN `sessions` ON `sessions`.`challenge_id` = `challenges`.`id` ORDER BY `sessions`.`score` DESC
Sequelize support this type of query with it's ORM Model.

Sequelize Model Relationship

I have 2 models here -
user.js
module.exports = (sequelize, DataType) => {
const User = sequelize.define('user', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataType.INTEGER
},
username: {
type: DataType.STRING,
unique: true,
validate: {
len:
{ args: [4, 20], msg: "Username should be contain 4-20 characters." },
isAlphanumeric:
{ msg: "Only letters and numbers are allowed" }
}
},
email: {
type: DataType.STRING,
unique: true,
validate: {
isEmail:
{ msg: "Provide proper email" }
}
},
password: DataType.STRING,
emailverified: DataType.BOOLEAN
});
User.associate = function (models) {
// associations can be defined here
};
userprofile.js
module.exports = (sequelize, DataTypes) => {
var userprofile = sequelize.define('userprofile', {
nickName: DataTypes.STRING,
firstName: DataTypes.STRING,
middleName: DataTypes.STRING,
lastName: DataTypes.STRING,
gender: DataTypes.INTEGER,
age: DataTypes.INTEGER,
country: DataTypes.INTEGER,
steamUrl: DataTypes.STRING,
city: DataTypes.INTEGER,
status: DataTypes.STRING
}, {});
userprofile.associate = function (models) {
// associations can be defined here
};
return userprofile;
};
Can someone give an example on how to set 1: N relationship from user to userprofile i.e, 1 user can have N number of userprofiles and also by creating this relationship will a record be auto-generated under userprofiles table whenever a user is created?
Thank you
Did some research -
ref: https://github.com/sequelize/express-example/blob/master/models/user.js
module.exports = (sequelize, DataType) => {
const User = sequelize.define('user', {
id: {
autoIncrement: true,
primaryKey: true,
type: DataType.INTEGER
},
username: {
type: DataType.STRING,
unique: true,
validate: {
len:
{ args: [4, 20], msg: "Username should be contain 4-20 characters." },
isAlphanumeric:
{ msg: "Only letters and numbers are allowed" }
}
},
email: {
type: DataType.STRING,
unique: true,
validate: {
isEmail:
{ msg: "Provide proper email" }
}
},
password: DataType.STRING,
emailverified: DataType.BOOLEAN
});
User.associate = (models) => {
User.hasMany(models.userprofile, {
foreignKey: 'userid',
});
};
The above code creates a foreign key in userprofile table and auto-generation is not done.

Define Sequelize model such as all inserted entries should be in lowercase

I need to insert first_name and last_name in a lower case using sequelize and NodeJS.
How do I define a model where all entries should be in lower case?
const Users = sequelize.define('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
},
mobile : {
type: Sequelize.STRING,
}
first_name: {
type: Sequelize.STRING,
},
last_name :{
type: Sequelize.STRING,
},
email :{
type: Sequelize.STRING,
}
},
{
freezeTableName: true // Model tableName will be the same as the model name
},
{
where: {
$and: [
sequelize.where(sequelize.fn('lower', sequelize.col('first_name'))),
sequelize.where(sequelize.fn('lower', sequelize.col('last_name')))
]
}
}
);
What you're looking for is beforeCreate() sequelize hook:
const Users = sequelize.define('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
},
mobile : {
type: Sequelize.STRING,
}
first_name: {
type: Sequelize.STRING,
},
last_name :{
type: Sequelize.STRING,
},
email :{
type: Sequelize.STRING,
}
},
{
freezeTableName: true
},
hooks: {
beforeCreate: function(user){
user.first_name = user.first_name.toLowerCase();
user.last_name = user.last_name.toLowerCase();
return user;
}
}
);