Sequelize association from array of JSONs - node.js

Is it possible to make an association in sequelize from a model with a column which is array of json
timeLine:[
{
userId:2,
status:Started
},
{
userId:3,
status:Ended
}
]
timeLine is a column in case table.
I want a cases which was started by given user.

On a high level you need to create two models.
User
Case
User would have a foreign key id to the Case table.
Next in the Case model, establish a one-to-many relationship so that you can do a Case.timeline to pull up the array of users.
// example of how to establish the one-to-many relationship
Case.hasMany(models.user, {
as: 'timeline',
foreignKey: {
name: 'caseId',
allowNull: false
}
});

Related

Sequelize hasOne with BelongsToMany

I have to models DistrictArea and Order which Order must have a DistrictArea instance in it.
so I have done this so far:
Order.hasOne(models.DistricArea)
and in migration file I used this.
queryInterface.addColumn('Orders', 'district_area_id', {
type: Sequelize.INTEGER,
references: {
model: 'DistricAreas',
key: 'id'
}
})
and I have two questions. If we use associated methods in the model , we have to explicitly define these field to our models?
district_area_id: DataTypes.INTEGER
and do I need to define belongsTo in another model (DistricArea)?
the second question is I didn't define any field in DistricArea that associated with Orders. but when I want to use query DistricArea.findAll() it comes with this error:
"column "OrderId" does not exist"
so this is the goal I am trying to achieve:
I need to tell we have many orders that, every order has a
DistricArea.
Yes you still need to define the fields in your model
from what you described above it should be belongsTo instead of hasOne for order model , and hasMany in DistricArea model and then define your sourceKey using your district_area_id field.
Order.belongsTo(models.DistricArea,{foreignKey: 'district_area_id'})
DistricArea.hasMany(models.Order, {foreignKey: 'district_area_id', sourceKey: 'id'})
after this , in DistricArea.findAll() you would get all DistricArea and then inside you will have a Order array which contain every order for each DistricArea, or in a Order.findAll() call you will see all orders with a field district_area_id

referencing a model that hasn't been created, avoid the error: relation "TABLENAME" does not exist

I am very new to sequelize and postgresql. I looked a lot for an answer to this issue but I couldn't find anything related to my it. If this question is has an answer in another post I apologize for repeating and I'll gladly refer to the other post and remove my post from here.
At the beginning I did:
sequelize model:generate --name user --attributes username:string,email:string,password:string,collection_id:INTEGER
where collection_id references another table ID. I did the same for the collection table:
sequelize model:generate --name collection --attributes plant_id:integer,user_id:integer
in my models I updated the association
in the collection model I added:
models.collection.belongsTo(models.user, {foreignKey: 'user_id'})
and in the user model I added:
models.user.hasOne(models.collection, {foreignKey: 'collection_id'})
And in the migration files I added:
user_id: {
type: Sequelize.INTEGER,
references: {
model: {
tableName: 'user'
}
}
}
collection_id: {
type: Sequelize.INTEGER,
references: {
model: {
tableName: 'collection'
}
}
}
in their respective files. Now the issue here is that sequelize is trying to migrate the user model before the collection model, however the later is referenced in the first model and I am getting this error "relation "collection" does not exist" which only makes sense. Now if I removed the reference, is there a way to add it later after I migrate?
reference sets a foreign key on the table under the hood. But you can't have 2 tables with foreign keys pointing to each other (circular reference).
You set a foreign key on the "child" table which points to the "parent" table. In your case, if collection belongs to user then collection is "child".
You can read this paragraph from Sequalize docs with some details about the difference between hasOne and belongsTo (and read about those associations in Sequalize separately as well). {foreignKey: 'collection_id'} which you pass to hasOne method is actually supposed to be in collections table (target model), means in your case it doesn't make sense and should be like this instead:
models.user.hasOne(models.collection, {foreignKey: 'user_id'})
So, you don't need collection_id column in your user table, can safely remove it.

Node/Express Project: Create and Sync a "Join Class/Model" to a Postgres Database

I'm building a Node/Express/Postgres version of an app that I already built in Rails. I'm learning Node, so I figured I'd rebuild something that I know works.
For now, I'm dumping everything in one file (set up my database, defined my models, etc.), just to make sure I have everything set up correctly before I divvy them up into different files.
I set up my postgres database at the very top of the file, like so:
var Sequelize = require('sequelize');
var db = new Sequelize('my_database_name', 'my_username', null, {
host: 'localhost',
dialect: 'postgres',
});
With regard to my models, I have a Politician model:
var Politician = db.define("politician", {
name: {
type: Sequelize.STRING,
},
politicalParty: {
type: Sequelize.STRING
}
});
A Category model:
var Category = db.define("category", {
name: {
type: Sequelize.STRING
},
keywords: {
type: Sequelize.ARRAY(Sequelize.TEXT)
},
});
And a join model of Politician and Category, called "Interest". Because Interest is a join model, it will have a "politicianId" and "categoryId" properties....but will those properties automatically generate in the database? And so, is this how I would define the Interest model, with no properties?
Interest Model:
var Interest = db.define("interest")
Or, will I have to be specific, and create "politicianId" and "categoryId" properties? Like so:
Interest Model:
var Interest = db.define("interest", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
categoryId: {
type: Sequelize.INTEGER,
foreignKey: true
},
politicianId: {
type: Sequelize.INTEGER,
foreignKey: true
}
});
Also, do I need the "foreignKey: true" bit? Or will it automatically know that those properties are foreign keys? Also, do I need the "id" property? I know models automatically create their own primary key "id"...but again, I've been at this for hours, looking at docs, and trying everything.
I then defined my associations (again, all of this is the same file):
Politician.belongsToMany(Category, {through: "Interest"});
Category.belongsToMany(Politician, {through: "Interest"});
The Node/Sequelize docs seems to suggest that defining those 2 associations above will automatically "create a new model called Interest with the equivalent foreign keys politicianId and categoryId." So, do I even need to define a "Interest" model? Also, do I need the follow associations to describe that Interest belongs to Politician and Category?
Interest.belongsTo(Politician);
Interest.belongsTo(Category);
If I don't write the associations saying that Interest belongs to Politican and Catetory, I don't get the "politicianId" and "categoryId" columns in the Interest table. Just the "id" and createdAt/updatedAt columns.
I then created an instance of Politician, Category, and Interest, to persist everything to the database, to see if everything is there and set up correctly:
Politician Object:
var politician1 = Politician.sync({force: true}).then(function(){
return Politician.create(aPoliticianObjectDefinedInthisFile);
});
This works perfectly. I see this object in the politician table in the database.
Category Object:
var category1 = Category.sync({force: true}).then(function(){
return Category.create(aCategoryObjectDefinedInThisFile);
});
This works perfectly. I see this object in the category table in the database.
Here is what doesn't work. Creating an instance/object of Interest and synching it to the database. My thinking is, if I put integers as values, it will know that "politicianId: 1" means point to the politician object with an id of 1, and the same for "categoryId: 1". But when I write it as I have it below, the Interest table doesn't even show up in the Postgres database at all.
Interest Object:
Interest.sync({force: true}).then(function(){
return Interest.create(
{
politicianId: 1,
categoryId: 1
}
);
});
However, when I create the object of Interest like this, with no properties defined, the Interest table appears in the database, along with the "politicianId" and "categoryId" columns, however, those columns are empty. The object's primary id is in there at 1, and the "createdAt" and "updatedAt" columns have data too. But the foreign key columns are blank.
Interest Object:
Interest.sync({force: true}).then(function()
{
return Interest.create(
{
// No properties defined.
}
);
}
);
Sorry for this long post, lol, but, in all:
Am I creating the "Interest" model correctly?
Am I writing the associations for "Interest" correctly?
Do I even need to write associations for Interest, if I already have associations for its parent classes, Politican and Category defined?
In my Rails app, my associations for Politican and Category are like so:
Politician has_many interests
Politican has_many categories through interests
Category has_many interests
Category has_many politicians through interests
Interest belongs_to politician
Interest belongs_to category
But I use the "belongsToMay" association in Node because I got an error telling me to do so.
Basically, I need to create an instance of Politician, an instance of Category, and an instance of Interest that has "politicianId" and "categoryId" columns that point to those aforementioned instances of those classes.
politicanABC -- id: 1
categoryABC -- id: 1
instanceABC -- id: 1; politicanId: 1 (referring to politicanABC); categoryid: 1 (referring to categoryABC).
My app is set up like that in Rails and works wonderfully.
Help and thank you in advance :-)
You don't have to define the Interest model if you are not going to add any additional fields. Sequelize will internally define the model and add all required fields once you do following:
Politician.belongsToMany(Category, {through: "Interest"});
Category.belongsToMany(Politician, {through: "Interest"});
Sync needs to run on database level and not on tables since Interest model is implicit at this point.
db.sync({force: true});
Sequelize will add relationship build methods on both Politician and Category instances. Category will have methods addPolitician(), addPoliticians([]), setPoliticians([]), getPliticians(). Politician instances will have similar functions to associate categories to them. You can connect these after create option is performed on both objects successfully.
Politician.create({name: 'John Doe', politicalParty: 'Nice Party'})
.then(function(politician) {
Category.create({name: 'Nicers'})
.then(function(category) {
politician.addCategory(category);
});
});
You can also search and associate existing items using helper methods. Alternatively you can associate objects manually by accessing db.models.Interest model and running creates on it.

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?

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
});

Resources