I have a problems in sequelize to create a relationship between to models that both have composite keys. Let me show you the tables.
Usually to create a relationship between to models in sequelize, we use belongsTo or hasMany etc, and then set the foreignKey to the primaryKey of the target table (e.g. toolsName || tools_name). In my case I need to create a relationship of historyTool that belongsTo tools, so the code will look like this.
models.ChecklistTool.belongsTo(models.Tools, {
foreignKey: 'toolsName',
as: 'Tools'
}
);
Now, the problem is table tools set the clusterId as its another primaryKey which resulting a composite primary key for table (e.g. (glasses)(1)), I'm confused how to create the associate models.
While I realize it will be much easier if table tools has its own auto increment id (tools_id), it will be much help if I know how to create one without it, since it will be a good references in the future when I don't have any control in designing the tables.
Thank you so much, any help will be appreciated.
I just write it in SQL, use sequelize.query() method and get along with it.
Related
I'm building a social media demo app and to add friends functionality to that app.
In database I am thinking about making new table(model in sequelize) which contains user1 id and user2 id and a status with one character (accepted, rejected etc).
I tried implementing it but faced some issue: Now i need to have unique key but for combination of user 1 and user 2 (pair of user1 and user2 id).
How do I implement something like this using sequelize and also I don't think this is the best way to do it, so if you have a better way please let me know, thanks.
Your description is somewhat lacking and missing some components. However it is clear enough to see what you are describing
is a many-to-many (m:m) relationship. It is just that the both sides come from the same table. While not the most common relationship,
neither is it too unusual. Further the resolution is the same as any other m:m. Create another table that has the key to both sides
as foreign keys. There is one slightly unusual twist in that the combination (parent1, parent2)(P1,P2) and the combination (P2,P1)
should be considered the same. This introduces a slight twist to the norm; instead of generating a PK from the the parent columns
the PK will be just be sequence generated (technically the PK is not required unless there are anticipated child tables of it).
We then create a unique index on the ordered pair (P1,P2). So something along the line of:
create table friends( f_id integer generated always as identity
, user_id_1 integer not null
, user_id_2 integer not null
, status varchar(1) not null default 'P'
, friends_since date not null default now()::date
, constraint friends_pk primary key(f_id)
, constraint f2user_1_fk foreign key(user_id_1)
references users(user_id)
, constraint f2user_2_fk foreign key(user_id_2)
references users(user_id)
, constraint cannot_friend_self
check (user_id_1 != user_id_2)
);
--
-- unique index to recognize (P1,P2) = (P2,P1)
create unique index already_friends on friends
( least(user_id_1,user_id_2), greatest(user_id_1,user_id_2) );
See fiddle here for examples. The bi-directional nature of Friends table causes additional complications within the queries. Typically I hide complication within SQL functions. I have also added a couple useful functions. You should be able to uses these as examples. Note, since they are SQL functions you can extract the statement and convert to a parameterized query.
Sorry, I do not know sequelize so I will not guess at the translation, but there seem to be many examples of the internet for all the above.
Preamble
I'm somewhat new to Loopback 4, and I have successfully created 2 working CRUD controllers, repositories, models, etc. I have Users and Organizations, and I am have successfully created a M:M relation between Users and Organizations using the relation generator. So, I can create a user, create an organization, and separately I can link them together in a many-to-many table called "membership". All of this follows (as far as I know) loopback best practices per their docs.
Question:
How do I make sure that each record in the membership table is unique?
here's an example of my table with duplicates
For example, User #1, Jeff, joins Organization #1, Amazon. Some erroneous code then attempts to add Jeff to Amazon a 2nd time, I want this to fail.
I was thinking I could simply check the database if the record exists, but it seems cleaner to add this constraint to the model, so that any attempted insert would fail if duplicate. I have dug around in the docs and haven't found anything.
Any help is appreciated!
In database design, a unique constraint would be enforced by a compound/composite key on the junction table. This would enforce a unique pair of orgId and userId.
Hence, the junction table should have only 2 columns:
orgId
userId
To create a composite key in LoopBack 4, update the through model as follows:
// Some parts were omitted for bevity
#model()
export class OrgUser extends Entity {
#property({id: 1})
orgId: number;
#property({id: 2})
userId: number;
constructor(data?: Partial<OrgUser>) {
super(data);
}
}
I have two models that need to be connected in a one-to-one association: Coach and Team. A team only has one coach and a coach only has one team.
I need to be able to include from both sides: sometimes I query the Coach and include the Team, sometimes I query the Team and include the Coach.
Now I'm not sure: do I need to create reference columns on each table (CoachId in table "Teams" and TeamId in table "Coaches")?
I have tried creating those two columns and established the association like so:
module.exports = models => {
models.Coach.hasOne(models.Team)
models.Team.belongsTo(models.Coach)
}
But for some reason, when I'm creating a Coach and setting the existing TeamId, the TeamId column stays empty. Also, even if it would have been filled, it feels odd to also have to update the Coach row with the correct TeamId.
Can it all be accomplished in one write and then be queried from both sides as suggested above? Feels like I still have not understood something fundamental about Sequelize, even after working with it for a while.
Thanks!
to query from both sides, you need to use a through table
module.exports = models => {
models.Coach.hasOne(models.Team)
models.Team.belongsTo(models.Coach, {through: 'TeamCoach'})
}
TeamCoach will have primary keys from both tables linked such that it can allow for a bi directional query.
I am new to Sails js. I was trying for Customer and Account relationship(Many to Many).
I am able to create relationship between them. The joined collection which gets created when I insert first record, takes 'modelname1_attributename_ modelname2_attributename.
Can we give custom name to it as it will be easy to work with it further?.
I come from JAVA and Hibernate background and there is annotation in Hibernate which does the task I want.
Please help me to sort out this problem.
There is no way to change name of the automatically-generated "through" table used for Sails many-to-many associations. However, you can specify the "through" table manually, instead of using the automatically-generated one, and then name it anything you want. From the Sails.js docs on through associations:
Many-to-Many through associations behave the same way as many-to-many associations with the exception of the join table being automatically created for you. In a Many-To-Many through assocation you define a model containing two fields that correspond to the two models you will be joining together. When defining an association you will add the through key to show that the model should be used rather than the automatic join table.
So in your case you'd create a new model, e.g. api/models/CustomerAccount.js, like:
module.exports = {
attributes: {
customer:{
model:'customer'
},
account: {
model: 'account'
}
}
}
And then in the Customer.js and Account.js model files, use the through property when defining the association attributes, e.g. in Customer:
accounts: {
collection: 'customer',
via: 'customers',
through: 'customeraccount'
}
As #zabware notes in his answer, you can use tableName to further customize the name of this table.
I'm working with a database that I can't change, and I'm working with EF database-first...
I've got some tables with a many-to-many relation to a 'shared' table.
The relation based on the keys is many-to-many, but it's actually zero-or-one-to-many relation made unique by a fixed value in the shared table.
Example:
Table1; field:code, ...
Table2; field:code, ...
SharedTable; key1:code, key2:tablename, ...
If I use the EF designer to model this, I can only use the Table1:code to SharedTable:key1 for the assiociation, resulting in a many-to-many relation which is not allowed.
Is there any way to 'model' these associations to include a fixed value for SharedTable:key2, or force many-to-many relations to be allowed, so I could add the 'where key2=tablename' and ' manually for example?
Of course I could always resort to dropping the associations and joining manually...