Waterline relations in SailsJS - javascript

I write an application in SailsJS and i have a problem with relations,
some code at the beginning:
User.js
module.exports = {
tableName: 'user',
attributes: {
schedules: { collection: 'userworkstationschedule', via: 'user' },
}
UserWorkstationSchedule.js
module.exports = {
tableName: 'user_workstation_schedule',
attributes: {
user: { model: 'user', required: true },
}
}
After run my code in Postaman, in JSON response i get:
{
...
"user": 2,
...
}
I get only ID of my user, but i want to get a whole object of User model with his firstname, lastname, etc.
Ccould anyone help me?

I'm more accustomed to a sails 0.12, but I know there you can configure your app so that population happens automatically, but it is not the default - to do this, go into config/blueprints.js and set the populate option to true.
However, I recommend against this - population may not be something you need on every page / every api call. You can make your api calls with population requests built in, like so:
/api/userworkstationschedule/[workstationid]?populate=user
That should make the populate happen just for that api call.

Related

TypeORM findOne with nested relations

I am having some issues performing a nested find query with TypeORM. Here's the basic code:
const { completionId } = req?.params;
const user = req.user;
const retrievedCompletion = await getRepository(
CompletionGoogleSearch
).findOne({
relations: ['run', 'run.user'],
where: {
id: completionId,
// run: { user: { id: user.id } }, // This is the code that breaks the function
},
});
console.log(retrievedCompletion?.run.user.id);
console.log(user.id);
It looks to me like there's nothing out of order, and that the query should run. Any idea on what I am doing wrong? I know I can get around this issue by writing a querybuilder query or using raw SQL–I am just curious to understand if there's a flaw in my code.
typeorm added the ability to use nested object
userRepository.find({
relations: {
profile: true,
photos: true,
videos: {
videoAttributes: true,
},
},
});
on this way, you can fetch the data without using eager.
You can find more information here
The feature you're asking about doesn't supported on typeorm yet (Feb 2021).
Checkout this issue that was opened on 2018.
the Solution is use eager:true in run.user entity :
#OneToOne(() => User, User=> User.run, {
eager:true
})
user: User;
and next time you search in CompletionGoogleSearch do just relations: ['run'] and user will come with it.

Firebase nested queries slow - sendRequest call when we're not connected not allowed

I want to implement a follow system between users.
For that, I want to display all of the 250 users of my app, then add a checkmark button next to the ones I already follow, and an empty button next to the ones I do not follow.
var usersRef = firebase.database().ref(‘/users’);
var followingRef = firebase.database().ref(‘/followingByUser’);
var displayedUsers = [];
// I loop through all users of my app
usersRef.once('value', users => {
users.forEach(user => {
// For each user, I check if I already follow him or not
followingRef.child(myUid).child(user.key).once('value', follow => {
if (follow.val()) {
// I do follow this user, follow button is on
displayedUsers.push({
name: user.val().name,
following: true
});
} else {
// I do not follow this user, follow button is off
displayedUsers.push({
name: user.val().name,
following: false
});
}
})
})
})
When doing that, I often (not always) get the following error: "Error: Firebase Database (4.1.3) INTERNAL ASSERT FAILED: sendRequest call when we're not connected not allowed."

Eventually, all the data is fetched, but after 10 seconds instead of 1 (without the error).
I do not believe it is an internet connection issue, as I have a very fast and stable wifi.
Is it a bad practice to nest queries like that?
If not, why do I get this error?
My data is structured as below:
users: {
userId1: {
name: User 1,
email: email#exemple.com,
avatar: url.com
},
userId2: {
name: User 2,
email: email#exemple.com,
avatar: url.com
},
...
}
followByUser: {
userId1: {
userId2: true,
userId10: true,
userId223: true
},
userId2: {
userId23: true,
userId100: true,
userId203: true
},
...
}
Your current database structure allows you to efficiently look up who each user is following. As you've found out it does not allow you to look who a user is follow by. If you also want to allow an efficient lookup of the latter, you should add additional data to your model:
followedByUser: {
userId2: {
userId1: true,
}
userId10: {
userId1: true,
},
userId223: {
userId1: true,
},
...
}
This is a quite common pattern in Firebase and other NoSQL databases: you often expand your data model to allow the use-cases that your app needs.
Also see my explanation on modeling many-to-many relations and the AskFirebase video on the same topic.

How to create foreign keys with sequelizejs in a feathersjs project

I am using featherjs v2.0.3 with sequelize v3.29.0 and I just created three models, the third having a relationship to the other two.
I used the feathers-cli to generate services for each and then edit the model file of each.
So far, so good, the tables are created (using PostgreSQL), indexes are created, feathersjs takes care of the CRUD nicely, but not foreign keys yet.
So, when I try to tell feathersjs the relationship between the models, I get in trouble.
When I add role_permission.belongsTo(permissions) to the role_permission model, I get this error:
ReferenceError: permissions is not defined
As I've seen in the Sequelize documentation, the models are defined in the same "document", hence I suspect the problem is somewhere there, but I don't understand what need to be done.
Finally, here's the relevant parts of the model definitions of permission and role_permission:
// permission-model.js - A sequelize model
module.exports = function(sequelize) {
const permission = sequelize.define('permissions', {
permission_id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV1,
primaryKey: true,
allowNull: false
}...
}, ...);
permission.sync();
return permission;
};
// role_permission-model.js - A sequelize model
module.exports = function(sequelize) {
const role_permission = sequelize.define('role_permissions', {
permission_id: {
type: Sequelize.UUID,
allowNull: false
}...
}, ...);
role_permission.belongsTo(permissions) //<-- undefined?
role_permission.sync();
return role_permission;
};
Do you have any pointers to help me solve this?
Thanks!
You need to import the permissions model. But it may or may not be defined yet.
Here's a method I discovered from #mrpatiwi on github to ensure every model is loaded before the associations are set up.
First, when you need to define a relationship add a classMethod called associate that accepts all the models and sets up the relationships.
module.exports = function(sequelize) {
const role_permission = sequelize.define('role_permisson', {
...
}, {
classMethods: {
associate(models) {
role_permission.belongsTo(models.permission);
},
},
});
// Don't add role_premission.sync() here
return role_permission;
};
Then, in src/services/index.js at the end of the module.exports function, add:
// Setup relationships
const models = sequelize.models;
Object.keys(models)
.map(name => models[name])
.filter(model => model.associate)
.forEach(model => model.associate(models));
sequalize.sync();
I had the same issue and resolved it simply by changing this:
role_permission.belongsTo(permissions)
to this:
role_permission.belongsTo(models.permissions)
(I used the Feathers CLI to generate the models today, 9 Aug 2018)

Is there a way to save multiple embedded models in db at once using Sequelize

Suppose we have a such structure in NodeJs Sequelize.
var User = sequelize.define('user', {/* ... */})
var Project = sequelize.define('project', {/* ... */})
Project.hasMany(User)
In this part of video presenter offers to save embedded objects with two steps using promises. In our case it would be something like:
Project.create({
...
}).then(function(project){
User.create({
...
projectId:project.id
})
})
But this approach will result two db calls.
So, is it possible to save embedded objects (Project which contains User e.g. User must have Project's id as a foreign key) into the db with one db call or within a transaction using Sequelize?
You should be able to insert parent-children by passing an array of objects into a key with the same name as the "as" value used on the "include". Although the documentation is light on the usage, you can see it handled in the source code here.
No promises (pun semi-intended) that this is actually run in single SQL query, not sure of the exact implementation in Sequelize. You should be able to enable logging (logging: console.log in the Sequelize(options)) to see what it's running.
// specify an "as" value and require a User.project_id value
Project.hasMany(User, { as: 'Users', foreignKey: { allowNull: false } });
// define your Project -> Users as json with the "as" value as the key
const project = {
name: 'project name',
Users: [
{
name: 'user 1',
},
{
name: 'user 2',
},
],
};
// create a transaction and "include" the Model in the create, txn falls back in .catch()
sequelize.transaction(t =>
Project.create(project, {
include: [{
model: User,
as: 'Users',
}],
transaction: t,
})
)
.catch(e => console.log('the txn failed because', e));

Sails.js filtering records using the route

I am very new to Sails.js and I am trying to understand its magic.
I have three nested models using associations : Series.js -> Season.js -> and Episode.js.
Series.js
module.exports = {
attributes: {
/* other attributes */
seasons: {
collection: 'season',
via: 'series'
}
}
};
Season.js
module.exports = {
attributes: {
/* other attributes */
episodes: {
collection: 'episode',
via: 'season'
},
series: {
model: 'series'
}
}
};
Episode.js
module.exports = {
attributes: {
/* other attributes */
season: {
model: 'season'
}
}
};
Out of the box, I can get the seasons of a series using the route:
/series/:id/seasons
And also the episodes of a season using the route:
/seasons/:id/episodes
What I don't understand is why I can't get the episodes of a season of a series using this route:
series/:id/seasons/:id/episodes
Any idea why is this happening? I know I could use custom routes to get the behaviour I want, but it'd be nice to be able to do it without any further configuration.
I know Sails.js only allows one level population, but this doesn't seem the issue since I have set populate: false.
Sails doesn't provide this route automatically:
series/:id/seasons/:id/episodes
because it doesn't really make sense if you think about it. If you already know the ID of the season, then the series it belongs to is irrelevant. Just use:
seasons/:id/episodes
to get the episodes you want.

Categories