Is there any way to do relation mapping between models in Sails.js?
Here is what I would like:
Video.js:
module.exports = {
attributes: {
filename: 'STRING',
length: 'INTEGER',
watchCount: 'INTEGER',
extension: 'STRING'
user: // I wan to reference to my User.js model
}
};
And in my User.js:
module.exports = {
attributes: {
username: {
type: 'email',
required: true
},
password: 'STRING',
videos: // I would like to have an array of videos after querying a user
}
};
You can use associations in sailsJs now by using the v0.10 branch
https://stackoverflow.com/a/21822843/1585332
The mapping would be something like this..
Video.js
module.exports = {
attributes: {
filename: 'STRING',
length: 'INTEGER',
watchCount: 'INTEGER',
extension: 'STRING'
user:{
model: "user"
}
}
};
User.js
module.exports = {
attributes: {
username: {
type: 'email',
required: true
},
password: 'STRING',
videos:{
collection: "video",
via: "user"
},
}
};
Sails.js doesn't support association yet, but they're working on it:
https://github.com/balderdashy/sails/issues/124#issuecomment-21690561
Also see: How to perform SQL Joins and Relations in Sails.js and Waterline?
For now I would just reference ID's and/or use the .query() method.
Related
I know it is possible to create a virtual reference using a local _id to a foreign ObjectId, but is it possible to use a local ObjectId to a foreign ObjectId?
I'm trying to figure out if I have a bug somewhere or if this is not possible because it's not working.
const Post = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
text: {
type: String,
}
})
const ProfileSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
bio: {
type: String,
max: 500,
}
});
ProfileSchema.virtual('posts', {
ref: 'Post',
localField: 'user',
foreignField: 'user',
});
// query
const profile = await Profile.findOne({
user: req.user.id,
}).populate('posts')
Yes it is possible, but you need to add { toJSON: { virtuals: true } } to the Schema.
const ProfileSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user',
},
bio: {
type: String,
max: 500,
},
},
{
toJSON: { virtuals: true },
}
);
From docs:
Keep in mind that virtuals are not included in toJSON() output by default. If you want populate virtuals to show up when using functions that rely on JSON.stringify(), like Express' res.json() function, set the virtuals: true option on your schema's toJSON options.
https://mongoosejs.com/docs/populate.html#populate-virtuals
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
}
}
)
i am doing a simple project with node.js using Sequelize with MySQL database. I was modeling my models associations. One got the hasMany and the other the belongsTo, I set the informations in both(like, as:...,foreignKey:...,onDelete:...), and set in foreignKey the propertie allowNull. When I save de model with the belongsTo method passing the in the request body the foreignKey it saves properly. But when I do this with model that uses in association the method hasOne it doesn't work. It passes that I need to specify the model ID that uses the belongsTo method.
const connection = require('../../config/database');
const DataTypes = require('sequelize').DataTypes;
const Course = connection.define('course', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
courseName: {
type: DataTypes.STRING(50),
field: 'course_name',
allowNull: false
}
},
{ timestamps: false });
Course.associate = models => {
Course.belongsTo(models.Lecturer, {
foreignKey: {
field: 'lecturer_id',
allowNull: false
},
as: 'lecturer'
});
Course.belongsToMany(models.Student, {
through: 'student_course',
as: 'students',
foreignKey: 'curse_id',
otherKey: 'student_id'
})
}
module.exports = Course;
const connection = require('../../config/database');
const DataTypes = require('sequelize').DataTypes;
const Lecturer = connection.define('lecturer', {
lecturerName: {
type: DataTypes.STRING(50),
field: 'lecturer_name',
allowNull: false
}
},
{ timestamps: false });
Lecturer.associate = models => {
Lecturer.hasOne(models.Course, {
foreignKey: {
field: 'lecturer_id',
allowNull: false
},
as: 'course'
})
}
module.exports = Lecturer;
Result:
[ ValidationErrorItem {
message: 'course.courseId cannot be null',
type: 'notNull Violation',
path: 'courseId',
value: null,
origin: 'CORE',
instance: [Object],
validatorKey: 'is_null',
validatorName: null,
validatorArgs: [] } ]
I can't comment yet, but it looks like the error shows a camel-case column name (courseId) as opposed to a snake-case column name (course_id).
Also, you have misspelled "course_id" in your Course.belongsToMany association.
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.
I've been trying a simple 'one way association' on v0.9.16 and later v.10.0.rc8.
I'm guessing, I'm doing something wrong.
I have two collections on my MongoDB and I have two models and a controller such as following;
my User.js file;
module.exports = {
connection: 'mongo',
attributes: {
username: {
type: 'string',
required: true
},
encryptedPassword: {
type: 'string' ,
required: true
},
//one way association
personel: {
model: 'Personel'
}
}
};
my Personel.js file;
module.exports = {
connection: 'mongo',
attributes: {
name: 'string',
phone: {
mobile: 'string',
office: 'string'
},
email: 'string',
gender: 'string'
department: {
department_id: 'integer',
department_name: 'string'
},
title: {
title_id: 'integer',
title_name: 'string'
}
}
};
my UserController.js file;
module.exports = {
show : function (req, res) {
User
.findOne(req.param('id'))
.populate('personel')
.exec(function(err, user) {
console.log(user);
});
}
Console writes 'undefined' for personel field;
{ username: 'jkidd',
personel_id: '1',
personel: undefined }
Edit
To provide association I've just added following codes to my User model
//one way association
personel: {
model: 'Personel'
}
and I'm trying to
show : function (req, res) {
User
.findOne(req.param('id'))
.populate('personel')
.exec(function(err, user) {
if(err) return res.json(err, 400);
if(!user) return res.json({ error: 'No User with that Id' }, 404);
console.log(user);
res.view({
user : user
});
});
}
You missed the Association in your Personel.js:
module.exports = {
connection: 'mongo',
attributes: {
department_id: 'integer',
department_name: 'string',
owner: {
model: "User"
}
},
}
See for more Info: http://beta.sailsjs.org/#/documentation/reference/Models/Associations/OnetoOne.html
Hint: You dont need to config the _id - waterline handle that for you!
Edit:
Also a Issue
And you cannot use "nested attributes" (see: How to translate models in Sails.js?). Change that also!
edit: you almost there... ;-)
module.exports = {
attributes: {
username: {
type: 'string',
required: true
},
encryptedPassword: {
type: 'string' ,
required: true
},
//one way association
personel: {
model: 'user'
},
},
};
and your personel.js
module.exports = {
attributes: {
name: 'string',
email: 'string',
gender: 'string',
owner: {
model: 'user',
},
},
};
I wanted to add a comment but cannot as my rep isn't high enough. As already stated. You missed the Association in your Personel.js.
With this in place waterline should link the models up but it isn't for some reason. I'd suggest removing your id attributes as these are likely confusing matters as you'll get _id added automatically for you which is what waterline will use for the associations.
In your code where you associate the personnel to user do so by setting user.personnel = personnel.id.
If you require more help can you post the code/commands you're using to associate the models too.
[EDIT]
With regards to nested attributes check Sails.js - how to update nested model
Your User model should be as follows:
module.exports = {
attributes: {
username: {
type: 'string',
required: true
},
encryptedPassword: {
type: 'string' ,
required: true
},
//one way association
personel: {
collection: 'personel',
via: 'user',
},
},
};
And your personel model:
module.exports = {
attributes: {
name: 'string',
email: 'string',
gender: 'string',
user: {
model: 'user',
},
},
};
And just a little modification to your controller so that you can view the JSON output in browser:
module.exports = {
show: function (req, res) {
User2.find()
.populate('personel')
.exec(function(err, user) {
console.log(user);
return res.send(200, user);
});
},
}
[EDIT]
I've just realised you weren't talking about a one to many association, the above is that, not a one to one.
Your edited code looks find for the one to one join. How are you creating the models? I think that's your issue, you need something like:
Personel.create({ name: 'personel'}, function(err, createdPersonel) {
User.create({ name: 'user', personel: createdPersonel.id }, function(err, createdUser) {
res.send(200, createdUser )
}
}
That's without error checking and assuming you're in a controller.