Foreign Keys in SailsJS Models and Databases - javascript

I've been trying to get a better understanding of how to setup Foreign Keys in SailsJS. I am currently working on a project for class in which my group needs to create an evaluation system with instructor and students profile to view the results. I've seen some examples online, but I have seen varies formats and I'm not sure what the correct format is suppose to look like.
User Model
/**
* User.js
*
* #description :: TODO: You might write a short summary of how this model works and what it represents here.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
// The user's anonymous ID (e.g. 1)
anonymousID: {
type: 'integer',
autoIncrement: true
},
// The user's first name (e.g. Bob)
firstName: {
type: 'string',
required: true
},
//The user's last name (e.g. Smith)
lastName: {
type: 'string',
required: true,
},
// The user's full name (e.g. Bob Smith)
fullName: {
type: 'string',
required: true
},
// The user's assigned NetID (e.g. abc123)
netID: {
type: 'string',
primaryKey: true,
required: true,
unique: true
},
// The user's nine digit SchoolID (e.g. 000-000-000)
schoolID: {
type: 'integer',
size: 9,
required: true,
unique: true
},
// The user's email address (e.g. netID#university.edu)
email: {
type: 'string',
email: true,
required: true,
unique: true
},
// The encrypted password for the user (e.g. asdgh8a249321e9dhgaslcbqn2913051#T(#GHASDGA)
encryptedPassword: {
type: 'string',
required: true
},
// The timestamp when the the user last logged in
// (i.e. sent a username and password to the server)
lastLoggedIn: {
type: 'date',
required: true,
defaultsTo: new Date(0)
},
// The user's academic title (e.g. student)
title: {
state:{
type : 'string',
required: true,
enum: ['Student', 'Faculty', 'Staff', 'Dean'],
defaultsTo: 'Staff'
}
},
// The user's academic classification (e.g. freshman)
classification: {
state: {
type: 'string',
required: true,
enum: ['Freshman', 'Sophomore', 'Junior', 'Senior', 'Graduate', 'N/A']
defaultsTo: 'N/A'
}
},
}
};
Schedule Model
/**
* Schedule.js
*
* #description :: TODO: You might write a short summary of how this model works and what it represents here.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
// The CRN ID (e.g. 32458)
courseID: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
// The Course Reference Name (e.g. MBW 1001)
course: {
type: 'string',
size: 8,
required: true
// Add FK code from Course Table
},
// The Course Name (e.g. Magical Basket Weaving)
title: {
type: 'string',
required: true
// Add FK code from Course Table
},
// The Course Instructor (e.g. ab123)
intructorID: {
type: 'string',
required: true
// Add FK code from User Table
},
// The Term refers to the semester (e.g. Fall 2015)
term: {
type: 'string',
required: true
},
}
};
Courses Model
/**
* Course.js
*
* #description :: TODO: You might write a short summary of how this model works and what it represents here.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
// The Evaluation ID (e.g. 1)
courseNum: {
type: 'integer',
autoIncrement: true
},
// The Department Name (e.g. Arts and Sciences)
department: {
type: 'string',
required: true
},
// The Course Reference Name (e.g. MBW 1001)
course: {
type: 'string',
primaryKey: true,
size: 8,
unique: true
},
// The Course Name (e.g. Magical Basket Weaving)
title: {
type: 'string',
required: true
},
}
};
Enrolled Model
/**
* Enrolled.js
*
* #description :: TODO: You might write a short summary of how this model works and what it represents here.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
// The Transaction ID (e.g. 32458)
transactionID: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
// The CRN ID (e.g. 32458)
courseID: {
type: 'integer',
required: true
// Add FK code from Schedule Table
},
// The Course Instructor (e.g. ab123)
instructorID: {
type: 'string',
required: true
// Add FK code from Schedule Table
},
// The Course Instructor (e.g. ab123)
studentID: {
type: 'string',
required: true
// Add FK code from User Table
},
// The Term refers to the semester (e.g. Fall 2015)
term: {
type: 'string',
required: true
},
// The Right to Submit an Evaluation (e.g. True or False)
evaluationStatus: {
type: 'boolean',
},
}
};
Evaluation Model
/**
* Evaluation.js
*
* #description :: TODO: You might write a short summary of how this model works and what it represents here.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
// The Evaluation ID (e.g. 1)
evaluationID: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
// The user's anonymous ID (e.g. 1)
anonymousID: {
type: 'string',
required: true,
// Add FK code from user table
},
// The Course Instructor (e.g. ab123)
intructorID: {
type: 'string',
required: true
// Add FK code from User Table
},
// The course's assigned CRN (e.g. 12343)
courseID: {
type: 'integer',
required: true,
size: 5
// Add FK code from schedule table
},
// The Course Reference Name (e.g. MBW 1001)
course: {
type: 'string',
size: 8,
},
// The rating of question 1
ratingOne: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 2
ratingTwo: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 3
ratingThree: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 4
ratingFour: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 5
ratingFive: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 6
ratingSix: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 7
ratingSeven: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 8
ratingEight: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 9
ratingNine: {
type: 'integer',
required: true,
size: 2
},
// The rating of question 10
ratingTen: {
type: 'integer',
required: true,
size: 2
},
// The positive feedback from student
positiveFeedback: {
type: 'string',
defaultsTo: 'N/A',
size: 4000
},
// The negative feedback from student
negativeFeedback: {
type: 'string',
defaultsTo: 'N/A',
size: 4000
},
// The General Rating of Evaluation (e.g. 8.76, SUM(ratings)/TotalRatings)
genRateEval: {
type: 'float',
required: true,
size: 4
},
// The Inaproprate Flag (e.g. True or False)
inaproprateFlag: {
type: 'boolean',
},
}
};
I've included all five models I'm working with so everyone can get a complete picture of how everything will/should connect.
From my understanding, the foreign key should be setup like the code snippet below.
Schedule Model (with Foreign Keys)
/**
* Schedule.js
*
* #description :: TODO: You might write a short summary of how this model works and what it represents here.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
attributes: {
// The CRN ID (e.g. 32458)
courseID: {
type: 'integer',
autoIncrement: true,
primaryKey: true
},
// The Course Reference Name (e.g. MBW 1001)
course: {
// Add FK code from Course Table
model: 'Course',
via: 'course'
},
// The Course Name (e.g. Magical Basket Weaving)
title: {
// Add FK code from Course Table
model: 'Course',
via: 'title'
},
// The Course Instructor (e.g. ab123)
intructorID: {
// Add FK code from User Table
model: 'User',
via: 'netID'
},
// The Term refers to the semester (e.g. Fall 2015)
term: {
type: 'string',
required: true
},
}
};
I'm not completely sure though if that's the proper way to setup foreign keys.

Yes, its the right way of setting up a foreign key in sails js. That being said, it varies on the type of association i.e., whether the relation is one to one or one to many.
Taking the examples from sailsjs website,
One to One relation:
myApp/api/models/pet.js
module.exports = {
attributes: {
name:'STRING',
color:'STRING',
owner:{
model:'user'
}
}
}
myApp/api/models/user.js
module.exports = {
attributes: {
name:'STRING',
age:'INTEGER',
pony:{
model: 'pet'
}
}
}
One to Many relation:
myApp/api/models/pet.js
module.exports = {
attributes: {
name:'STRING',
color:'STRING',
owner:{
model:'user'
}
}
}
myApp/api/models/user.js
module.exports = {
attributes: {
name:'STRING',
age:'INTEGER',
pets:{
collection: 'pet',
via: 'owner'
}
}
}
Sailsjs Associations

Your main problem is how to use association so first use the reference/documentation on the sails js official website http://sailsjs.org/documentation/concepts/models-and-orm/associations, and i think all your queries will be solved.

Related

How to sustainably organise user schema in mongoose

I have a user which should have the following fields and currently has following schema:
const UserSchema = new Schema(
{
email: {
type: String,
required: true,
index: { unique: true },
lowercase: true,
},
isVerified: { type: Boolean, default: false }, // whether user has confirmed his email
name: { type: String, required: false },
password: { type: String, required: true, minLength: 6 }, // object with next two included?
passwordResetExpires: Date,
passwordResetToken: String,
roles: [{ type: 'String' }], // Array of strings?
username: { type: String, required: false },
token: [{ type: String, required: false }], // used to send verification token via email
},
{ timestamps: true },
);
So yes, what is the world's default standard for organising user schemas. This schema's fields are pretty common, right?

Sails Js populate with conditions

I'm trying to multiple populate in sails js using sails-hook-deep-orm. I want to filter the province id.
I am using the latest version of Sails and Node. And I using MySQL for database.
This is my model :
// Province.js
attributes: {
name: {
type: 'string',
required: true
},
description: {
type: 'string',
required: false
},
cities: {
collection: 'city',
via: 'province'
}
}
// City.js
attributes: {
name: {
type: 'string',
required: true
},
description: {
type: 'string',
required: false
},
province: {
model: 'province'
},
communities: {
collection: 'community',
via: 'city'
}
}
// Community.js
attributes: {
name: {
type: 'string',
required: true
},
description: {
type: 'string',
required: false
},
cities: {
collection: 'city',
via: 'province'
}
}
I have try with :
Community.find()
.populate('city.province', {'city.province.id' : 1});
Community.find()
.populate('city.province', { where: { 'city.province.id': 1 } });
The code still not filtering. I Hope this case can be solved. Thank you :)
When you populate an association of your object, the name needs to be the name of the association in the parent object and not the name of the model you are referring to.
In your situation, Community has the association named 'cities'.
The next step is to filter the list of cities, this is the where statement as the second argument of the populate.
Community.find()
.populate('cities', {
where: {
province: 1
}
}
)

How do I access the data in the .pre('validation') hook?

I am having trouble with performing operations during the pre('validate') hook. I need to do some prevalidation (making sure at least one of 2 different fields is populated, but not necessarily both, for example).
const AccessorySchema = new Schema({
accessory: {
type: String,
required: true,
},
category: {
type: String,
required: true,
enum: [
'Offense',
'Defence',
'Miscellaneous'
]
},
space: {
type: Number,
required: true,
validate: {
validator: Number.isInteger,
message: 'Space must be an integer'
}
},
priceFixed: {
type: Number,
required: false,
validate: {
validator: Number.isInteger,
message: 'Fixed Price must be an integer'
}
},
priceMultiplier: {
type: [Schema.Types.Mixed],
required: false
},
weightFixed: {
type: Number,
required: false,
validate: {
validator: Number.isInteger,
message: 'Fixed Weight must be an integer'
}
},
weightMultiplier: {
type: [Schema.Types.Mixed],
required: false
},
vehicles: {
type: [String],
required: true,
enum: ["car","cycle"]
}
});
AccessorySchema.pre('validate', (next) => {
console.log(this);
next();
});
And I send it this object :
{
accessory: "some name",
category: "Miscellaneous",
priceMultiplier: [3,5],
weightMultiplier: [3,5],
space: 0,
vehicles: ["car"]
}
this logs {} and populates the mongo DB. But I can't check any of the properties in pre validation.
mongoose version is ^4.7.7, nodejs 6.10.2, mongodb version is 3.2.9
How can I access the data in the pre validation hook?
do not use arrow function, it doesn't bind the context.
Change your code to below
AccessorySchema.pre('validate', function(next){
console.log(this);
next();
});

Sails.js with mongodb design

just starting out in sails.
Currently I have a User Model set up. I also have another Founder Model to store information specific to Users who are also Models.
attributes: {
companyName: {
type: 'string',
required: true
},
tagLine: {
type: 'string',
required: true
},
location: {
type: 'string',
required: true
},
market: {
type: 'string',
required: true
},
psName: {
type: 'string',
required: true
},
psDesc: {
type: 'string'.
required: true
}
}
So my question in the FounderController...would inputting the unique id for the user from User for the database be implemented in the models or in the controller? The Founder model will essentially create it's own unique id.
My first approach would to basically find the ID from the User documents, store it into a variable, update the Founder document's id field with the user id?
I felt this isn't very efficient. Thanks.

Sails.Js - Simple Exercise with 2 Relations on the ORM

I'm new to Sails.js and Node.js, so if i'm asking a simple question please forgive me.
I'm doing an API that must have a database, and i wanted to implement MySQL because i have some relations between tables. So i wrote the relational model by hand, like it is on the figure:
And i tried to implement is using sails.js, but for some reason i can't get the relation Level to Score working while the User-Score relationship is working fine.
Here are my models:
User.JS
module.exports = {
attributes: {
name:{
type:'string',
required: true
},
address:{
type: 'string'
},
email:{
type: 'string',
email:true,
unique: true,
required: true
},
encryptedPassword:{
type: 'string'
},
tranusertoscore:{
collection:'scores',
via: 'transcoretouser'
}
}
}
Level.js
module.exports = {
attributes: {
lvl_name:{
type: 'string',
required: true
},
tranleveltoscore:{
collection: 'scores',
via: 'transcoretolevels'
}
}
};
and finally
Score.js
module.exports = {
attributes: {
lvl:{
type: 'string',
required: true
},
score:{
type: 'integer',
required: true
},
transcoretouser:{
model: 'user'
},
transcoretolevels:{
model: 'level'
}
}
};
So, can you guys tell me what i'm doing wrong?
Sorry to take your time if the answer is easy, but i tried to follow documentation and search about the subject and didn't find any relevant answers.

Categories

Resources