How to join two tables of PostgreSQL In node.js using Bookshelfjs - node.js

I have two table.
Users
id(pk)
name(varchar)
email(varchar)
role(Array)(Fk)
Roles
id(pk)
name(varchar)
I have created model for these table
var Users= bookshelf.Model.extend({
tableName: 'Users'
});
var Roles= bookshelf.Model.extend({
tableName: 'Roles'
});
Now what i want , with user info to get Role information , and in my case roles can be more then one. how i can achive it?

This is a classical many-to-many situation. Both models should have belongsTo defined and you should have a table named roles_users with corresponding ids.

Related

Force database tablename for collection relationship in Sails

In a sails project, considering a model User and a model Role, with a relationship between User and Role :
// `User.js
module.exports = {
attributes: {
...
roles: {
collection: 'role',
dominant: true
},
...
}
}
For the the database representation, sails/waterline will create following tables :
table user,
table role,
table like user_roles__role_roles_role to represent the collection
I know we can force the name for the models USER and ROLE
(with the property 'tablename' : http://sailsjs.com/documentation/concepts/models-and-orm/attributes).
But how can we force the name the relationship table ? (Especially this name is quite long and tends to exceed limit).
Assuming this is a two-way relationship, and the Role model has a users collection, Sails will expect a table named role_users__user_roles, which has the role id first, user id second.
Your example table name would require User to be dominant and would require the Role model to have an attribute named roles_role that is a User collection.
To create your own join table, you can use the through association method and add a new model that represents the relationship, perhaps UsersRoles, and specify the tableName in that model definition.
Examples of the through association:
sails
docs
similar question
gist from comments in that question

Multiple relation n:n to one table in sequelize

I am using Sequelize for PostgresSQL. For example: I've got two tables Friendship and User. To make friendship possible for every user, I've got two relations n:n.
Associations in Sequelize
User.hasMany(Friendship,
{
as: "friendshipsAsked",
foreignKey: "asked_user_id",
joinTableName: "friendship"
});
User.hasMany(Friendship,
{
as: "friendshipsAsking",
foreignKey: "asking_user_id",
joinTableName: "friendship"
});
Friendship.belongsTo(User,
{
...
});
Friendship.belongsTo(User,
{
...
});
My biggest problem is querying friendships for user. When I've got user model, I have to get user.getFriendshipsAsking() and user.getFriendshipsAsked() and then merge both.
Is there any possibility to change relations so I can have user.getFriendships() in SQL such that it will perform like SELECT * FROM frienships WHERE requesting_user_id = 'user.id' OR requested_user_id = 'user.id'?
I would like to have a better solution to model friendship between users in the database?

Loading a meta table as object

I have a table in my database called users. In this table I only store user ID, username and password. Now, in another table called user_meta, I have the following columns: id, uid, meta_key, meta_value. I'm trying to find a way for Bookshelf to automatically load all records in user_meta where uid == userid, and store them as model.meta[meta_key] = meta_value. Sadly, I haven't been able to find a way to make this possible.
If it is possible at all, the 2nd step would be to also save all values in model.meta back on update / insert, inserting records where meta_key doesn't exist for that user ID yet, and updating where it does.
Try to set the associations (relations) between the models:
var User = bookshelf.Model.extend({
tableName: 'users',
meta: function() {
return this.hasMany(Meta);
}
});
var Meta = bookshelf.Model.extend({
tableName: 'user_meta',
user: function() {
return this.belongsTo(User);
}
});
http://bookshelfjs.org/#one-to-many

How to implemet a Many-to-Many relationship in Sequelizejs which also have relationship attributes?

So there are a lot of answers that explain how you model a Many-to-Many relationship in sequelizejs using hasMany() etc. But none of them has explained how and where do you store attributes which are created due to such an association, for eg: A customer can belong to or have many merchants and a merchant can have many customers, one such attribute of this relationship is a unique customer_id for a particular merchant-cutomer. Now where should this key(and any other detail) reside if we follow this: Stackoverflow answer
If you want additional attributes in your join table, you can define a model for the join table in sequelize, before you define the association, and then tell sequelize that it should use that model for joining, instead of creating a new one:
Customer = sequelize.define('customer', {})
Merchant = sequelize.define('merchant', {})
MerchantCustomers = sequelize.define('merchant_customers', {
customer_id: DataTypes.INTEGER
})
Merchant.belongsToMany(Customer, { through: MerchantCustomers })
Customer.belongsToMany(Merchant, { through: MerchantCustomers })
customer.addMerchant(merchant, { customer_id: 42 })
http://docs.sequelizejs.com/en/latest/docs/associations/#belongs-to-many-associations
To access the join table attributes:
c.getMerchants().then(function (merchants) {
merchants[0].merchant_customer.customer_id // Or perhaps merchant_customers, can't remember
});

Return model where the pivot entry exists

I'm using BookshelfJS. I have two models users and posts. Obviously, the relationship here is many to many. So I have a pivot table post_user.
Now, given a user_id, I want to find all the posts for that user. So far, I've managed to do this using knex:
knex.select()
.from('post_user')
.where('user_id', user_id)
.then(function (pivots) {
// Now loop through pivots and return all the posts
// Using pivot.post_id
pivots.map(function(pivot) {})
});
Is there a cleaner way of doing this?
You'll want to define the many-to-many relationship in your Bookshelf models. Something like this:
var User = bookshelf.Model.extend({
tableName: 'users',
posts: function() {
return this.belongsToMany(Post);
}
});
var Post = bookshelf.Model.extend({
tableName: 'posts',
users: function() {
return this.belongsToMany(User);
}
});
By convention, the pivot table Bookshelf would be using is posts_users (table names combined with _, starting from the table that is alphabetically first). It should contain a user_id and a post_id (and a coposite PK of those two). If you don't wish to rename the pivot table, see the documentation for belongsToMany for instructions on how to define the table and ids of your pivot table.
After this, you can query your model with Bookshelf:
return new User().where('id', user_id)
.fetch({withRelated: 'posts'})
.then(function (user) {
var postCollection = user.get('posts');
// do something with the posts
});
See also the documentation for fetch.

Resources