Two Database tables related in two different ways...? - mysql

Im sort of scratching my head on this one. Here's the scenario. Im using Doctrine and YAML schema files:
I have a table User and a table Event
User looks like this:
User:
columns:
id:
type: integer(7)
email:
type: string(100)
display_name:
type: string(255)
fb_id:
type: string(100)
relations:
Event:
type: many
refClass: UserEvent
Event looks like this:
Event:
columns:
id:
type: integer(7)
initiator_id:
type: integer(7)
loc_latitude:
type: decimal(11)
loc_longitude:
type: decimal(11)
4sq_id:
type: integer(11)
relations:
User:
type: one
local: initiator_id
foreign: id
User:
type: many
refClass: UserEvent
As you can see the problem is this: A User (or 'initiator') can start many events, and an event can belong to one User ('initiator'). However, an event can also have many Users who join it, and a User can Join many events.
So Event and User end up being related in two different fashions. How does this work? Is it possible to do it this way or am i missing something?

I think you just need one many-to-many relationship between the two tables. UserEvent will tell you what users have what events (and vice versa)... and joining through UserEvent and adding WHERE user.id = event.initiator_id will give you access to a user's initiated events, assuming they also belong to those events.

You can just add an event_attendees table with the event id and user id as the two columns? Or is this not the question

Related

Sequelize - how to define a trigger in a model?

I am currently working with sequelize on RDS Aurora DB and I need to track which records in which tables were deleted - for this, I created a new table dbLog. Now I need to add a trigger to the database which saves the id of the record into dbLog table whenever that record in table t1 gets deleted. Basically, I need to cover two scenarios for already deployed databases and those who dont yet exist.
Database already exists. This is easy since I can create the trigger by raw query like this
CREATE TRIGGER trigger AFTER DELETE ON t1 FOR EACH ROW
INSERT INTO dbLog ( id, tableName, status, updatedAt )
VALUES (OLD.id, 't1', 'D', NOW())`
Database doesn't exist. This is problematic since it gets created by initiation of the model and then sequelize.sync(). So I cant just call a raw query, instead, I need to define this trigger in the model for t1 table. This is how I initiate the table (simplified)
t1.init(
{
id: {
type: new DataTypes.BIGINT,
autoIncrement: true,
primaryKey: true
},
name: {
type: new DataTypes.STRING,
allowNull: false
}
},
{
sequelize,
tableName: 't1',
}
);
The problem is that I dont know how to create that trigger. I tried putting something like this into the attributes section of t1.Init. But there is some problem, when I check the database for triggers, none was created. How can I fix it? And are even triggers created by this way 1:1 equivalent of triggers created by raw query? Thanks a lot.
hooks: {
afterDestroy: function(t1) {
DbLog.create({
id: t1.id,
tableName: 't1',
status: 'D',
updatedAt: '2015-10-02'
})
}
}
You should create triggers in a DB manually by executing a raw SQL query. If you are using migrations then just create a migration with a trigger creation (also a raw SQL query).

How to do joins in SequelizeJS?

This is my model definition of Room table
sequelize.define("room", {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
name: DataTypes.STRING,
business_id: {
type: DataTypes.INTEGER,
references: {
model:"business,
key: "id"
}
}
});
And this is of business
sequelize.define("business", {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
name: DataTypes.STRING,
});
Now consider I have id of the room with me and I want to get business related to that using the foreign key. In normal SQL I would easily do this using inner join
I know that there is something like Association used in Sequelize but then what is the use of defining a reference in the model definition?
As per the DOC :
Sometimes you may want to reference another table, without adding any
constraints, or associations. In that case you can manually add the
reference attributes to your schema definition, and mark the relations
between them.
Association :
Creating associations in sequelize is done by calling one of the
belongsTo / hasOne / hasMany / belongsToMany functions on a model (the
source), and providing another model as the first argument to the
function (the target).
hasOne - adds a foreign key to the target and singular association
mixins to the source.
belongsTo - add a foreign key and singular association mixins to the source.
hasMany - adds a foreign key to target and plural association mixins to the source.
belongsToMany - creates an N:M association with a join table and adds plural association mixins to the source. The junction table is
created with sourceId and targetId.
Creating an association will add a foreign key constraint to the
attributes. All associations use CASCADE on update and SET NULL on
delete, except for n:m, which also uses CASCADE on delete.
I think this will clear your doubts.

Sequelize Change Unique Composites

I'm using the sequelize syntax to generate a unique composite with two columns in a table like so:
sequelize.define('Group', {
code: {
type: DataTypes.STRING,
unique: 'GroupCompositeIndex'
},
active: {
type: DataTypes.BOOLEAN,
unique: 'GroupCompositeIndex'
}
});
The goal is to have many inactive versions of this group code and change which is active; only one at a time. I will be changing the active value to null on one record, and to 1 on another. I have never constructed a table to work like this. Will it behave the way I expect by precluding there from ever being 2 groups active with the same code, while permitting which group is active to change?

Sequelize - Junction table never created

I have been trying to build a simple 'messages' app.. After giving MongoDB a try, i found out its really best to do with MySQL.
So but instead of writing all tables / queries etc by hand, I want to learn building it from the ground up with an ORM, a.k. Sequelize.
Lets say I have a user table:
var User = sequelize.define('user', {
email: {
type: Sequelize.STRING,
validate: {
isEmail: true
//msg: "Email is invalid"
}
}
}
And a message table:
var Message = sequelize.define('message', {
message: {type: Sequelize.STRING},
sender: {type: Sequelize.STRING},
read: {type: Sequelize.BOOLEAN}
}
Every user can have many messages, and every message can have 2 users in the conversation.
So when i do this:
User.hasMany(Message);
Message.belongsToMany(User, {through: 'Conversation', foreign_key: 'id'});
User.sync();
Message.sync();
I would expect a 'junction table' named Conversations... Holding the user_id's.. And every message having a reference to the Conversation_id, But apparently its not true...
Does anybody know what the correct way is?
Thanks!
For create Conversations table you need sync all: sequelize.sync();.

Row level permissions in sails.js

I need row-level permissions in sails. I already looked at this and at other threads, but everybody says to just use policies.
But what I need isn't just limiting the ability to do e.g. find/update all elements of a table but to have permissions per database row that consider associations for permissions.
It would be great if the permissions support blueprints like the ember data adapter, nested create/update/find (with populate) and sockets.
So for example:
GET /:model/:id
should return and populate with such entries where certain associated conditions are met.
So for example, we have 4 models:
User (columns: id, name, email, pwd_hash, ...)
Project (columns: id, client, name, ...)
UserAssignment (columns: id, user, project, user_perms, ...)
Client (columns: id, name, ...)
User and Project are linked through UserAssignment - an advanced MM-Table. (Users may have special user_perms to different projects, such as read,write,manage). And a Project always has one Client.
Here's the corresponding sails models:
// User.js
attributes: {
name: 'string'
}
// Project.js
attributes: {
name: 'string',
client: {
model: 'client'
},
userAssignments: {
collection: 'userAssignment',
via: 'project'
}
}
// UserAssignment.js
attributes: {
userPerms: 'integer',
user: {
model:'user'
},
project: {
model:'project'
}
}
// Client.js
attributes: {
name: 'string',
projects: {
collection: 'project',
via: 'client'
}
}
So lets say the User with the ID=1 wants to access a list of Clients he is allowed to see, he calls
GET /clients/
Speaking in SQL:
SELECT client.*
FROM client
INNER JOIN project ON project.client = client.id
INNER JOIN user_assignment ON project.id = user_assignment.project
WHERE user_assignment.user = 1 and user_perms > 4
GROUP BY client.id;
And then also if we have certain Project managers, they can update associated UserAssignments etc.
Basically I thought the permissions could be based on role associations.
I tried several ways to implement this functionality. I tried _permission_read, _permission_write columns for all rows and other stuff like using populates for this but nothing seems to work right.
The above example is just a excerpt of many different kinds of models which I can filter based on SQL couldn't do nicely with Sails/Waterline.
Do I need custom SQL queries for this?
Is it possible to do this neatly with Sails?
Do I misunderstand policies and is there a way to implement such requirements with them?
Or shall I use SQL views instead of tables?
Thanks in advance!