SailsJs/Postgresql - How to create a one way association or one-to-many relation via an unique field - sails.js

I have two models:
PdfAnnotation.js:
module.exports = {
tableName: "pdf_annotations",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true
},
annotation_id: {
type: "string",
unique: true,
required: true,
},
comments: {
collection: "pdfcomments",
via: "fk_annotation_id"
}
}
};
PdfComments.js:
module.exports = {
tableName: "pdf_comments",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true,
},
fk_annotation_id: {
model: "pdfannotations",
},
comment_content: {
type: "string",
},
}
};
When I run these codes:
PdfAnnotations.create({
annotation_id: "test3",
});
PdfComments.create({
fk_annotation_id: 'test3',
comment_content: 'test',
});
I got this error:
I have followed the documentation: https://sailsjs.com/documentation/concepts/models-and-orm/associations/one-to-many.
The difference between my implementation and the docs is: the constraint I used for PdfComments to PdfAnnotations via an unique field annotation_id(string) not the primary key pk_id(number), so that I got the error.
For some reasons I don't want to use annotation_id as a primary key (such as its type is string)
I'm not familiar with Sails and its ORM, hope to see your help.

Try something like this:
const pdfannotation = await PdfAnnotations.create({
annotation_id: 'test3',
}).fetch();
const pdfcomment = await PdfComments.create({
fk_annotation_id: pdfannotation.id,
comment_content: 'test',
});

Related

How to develop nested condition query in mongoDB

I am pretty new to mongoDb and want to apply nested query.
I have a business schema like this:
const businessSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
businessType: {
type: Schema.Types.ObjectId,
ref: "businessCategory",
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
select: false,
},
review: {
type: [reviewSchema],
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
Business has a review where user can do the review and reviewSchema is
const reviewSchema = new mongoose.Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: "users",
required: true,
},
rating: {
type: Number,
enum: [1, 2, 3, 4, 5],
},
reviewArray: {
type: [singleReviewSchema],
},
},
{ timestamps: true }
);
One user can do many reviews, and it has reviewArray.
ReviewArray schema is
const singleReviewSchema = new mongoose.Schema(
{
title: {
type: String,
},
description: {
type: String,
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
How to fetch the business with a condition business: isDeleted:false and its reviews with singleReviewSchema: isDeleted:false
I dont know your model names, so please replace path with correct names
but it might look like:
businnesModel.find({isDeleted: false})
.populate({
path: 'reviewModelName',
model: 'review',
populate: {
path: 'reviewArray',
model: 'singleReviewModelName',
match: {
isDeleted : false
}
}
})
It should provide you array of businessModel documents - even when their singleReviews array will be empty (because all of reviews are deleted, or there was zero reviews). So you have to filter it out in JS.
To avoid filtering in JS, and to do it a bit more efficient way for mongodb, you can go with aggregate instead.

hasMany foreignKey not working in Sequelize

I have some models - kanban_cards, kanban_checklists, kanban_checkitems.
kanban_cards model:
export default (sequelize, DataTypes) => {
return sequelize.define('kanban_card', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
label: {
type: DataTypes.STRING,
allowNull: true,
},
listId: {
type: DataTypes.UUID,
allowNull: false
},
...
})
}
kanban_checklist:
export default (sequelize, DataTypes) => {
return sequelize.define('kanban_checklist', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
cardId: {
type: DataTypes.UUID,
allowNull: false,
}
})
}
And the association is:
const models = {
KanbanCards: KanbanCards(sequelize, Sequelize.DataTypes),
KanbanChecklists: KanbanChecklists(sequelize, Sequelize.DataTypes),
...
}
...
models.KanbanCards.hasMany(models.KanbanChecklists, { as: 'checklists', foreignKey: 'cardId' })
models.KanbanChecklists.belongsTo(models.KanbanCards)
It works fine if I use findAll, but if I try to create, it doesn't work.
It says.
column "kanbanCardId" of relation "kanban_checklists" does not exist
I am going to use cardId rather than kanbanCardId.
I tried to set references to cardId, but it didn't work either.
If you indicated an explicit foreign key column in hasMany you should do the same for the other part - belongsTo:
models.KanbanChecklists.belongsTo(models.KanbanCards, { foreignKey: 'cardId' })
Otherwise Sequelize generate a foreign key name itself like in your case kanbanCard+id:
The name of the foreign key in the join table (representing the target model) or an object representing the type definition for the other column (see Sequelize.define for syntax). When using an object, you can add a name property to set the name of the column. Defaults to the name of target + primary key of target

SequelizeDatabaseError: the operator does not exist : integer = boolean when using special methods on model instance

I have two models in Many-to-Many association : Agency and Customer.
UPDATE : (here are the models and association definition)
Agency :
const agency = (sequelize, DataTypes) => {
const Agency = sequelize.define('agency', {
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true,
}
},
});
Agency.associate = models => {
Agency.hasMany(models.User, { onDelete: 'CASCADE' });
Agency.belongsToMany(models.Customer, { onDelete: 'SET NULL', through: 'CustomerAgencies'});
};
return Agency;
};
export default agency;
Customer :
const customer = (sequelize, DataTypes) => {
const Customer = sequelize.define('customer', {
email: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
validate: {
notEmpty: true,
isEmail: true,
},
},
firstname: {
type: DataTypes.STRING,
allowNull: true,
validate: {
notEmpty: true,
}
},
lastname: {
type: DataTypes.STRING,
allowNull: true,
validate: {
notEmpty: true,
}
},
phone: {
type: DataTypes.INTEGER,
},
language: {
type: DataTypes.STRING,
},
});
Customer.associate = models => {
Customer.belongsToMany(models.Agency, { onDelete: 'SET NULL', through: 'CustomerAgencies'});
};
return Customer;
};
export default customer;
When i create some entries, there is no problem :
const agency = await models.Agency.findOrCreate({
where: { name: 'SunTour'},
defaults: {
name: 'SunTour'
}
});
const customer = await models.Customer.findOrCreate({
where: { email: 'paulo#example.com' },
defaults: {
email: 'paulo#example.com',
firstname: 'Paulo',
lastname: 'Dena',
phone: '0202020202',
},
});
But i'm trying to use the special methods of Sequelize that are available when two models are in relation.
Juste under the previous code example i wrote this to check is there is already an assocation between the two instances :
debug(await customer[0].hasAgency(agency));
The node server return me the error below for this line :
UnhandledPromiseRejectionWarning: SequelizeDatabaseError: the operator does not exist : integer = boolean
In the console the query executed is this one :
SELECT "agency"."id" FROM "agencies" AS "agency" INNER JOIN "CustomerAgencies" AS "CustomerAgencies" ON "agency"."id" = "CustomerAgencies"."agencyId" AND "CustomerAgencies"."customerId" = 1 WHERE ((("agency"."id" = 1 OR "agency"."id" = false)));
You can see that Sequelize query is using "agency.id = false" in his condition, i guess that's the problem.
Note : i'm using a PostGreSQL Database.
I guess the problem come from the PostGreSQL Database, but what can i do ?
Thanks in advance.

Sails js and Sequelize, no associations added to database

This is how my models are structured in sails:
myapp
--api
----controllers
----models
-----User.js
------Role.js
User.js
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
}
},
associations: function() {
User.hasOne(Role, {foreignKey: 'id', as: 'role' });
}
};
Role.js
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
}
}
};
After sails lift, in the postgresql I have users table with id, username, password, createdat and updatedat + roles table with id, name, createdat and updatedat. No foreignKey for Roles in Users table.
How I can fix this?
I'm using sails-hook-sequelize and sails-hook-sequelize-blueprints, can this occur because of them?
Thanks!
Edit:
The correct way was:
module.exports = {
attributes:{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
}
},
associations: function() {
User.hasOne(Role, {
as : 'role',
foreignKey: {
name: 'roleId',
allowNull: false
}
});
}
};
The createdAt and updatedAt columns are added by default unless you set the timestamps option to false. See the docs.
To add foreign key constraints, you need to define associations for the Roles model.

Getting "model is not associated with other Model" in sequelize when using belongsToMany

I am using sequelize with postgreSQL. I have two schemas namely User and Location. A User can have many Locations and a Location can have many Users.
My User Schema is as follows
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: Sequelize.STRING,
require: true
},
middleName: {
type: Sequelize.STRING,
require: false
},
lastName: {
type: Sequelize.STRING,
require: true
},
age: {
type: Sequelize.INTEGER,
require: false
},
email_Id: {
type: Sequelize.STRING,
require: true,
unique: true,
validate: {
isEmail: true
}
}
My Location Schema is as follows:
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
latitude: {
type: Sequelize.DOUBLE,
require: true
},
longitude: {
type: Sequelize.DOUBLE,
require: true
},
locationAddress: {
type: Sequelize.STRING
},
mailBoxNo: {
type: Sequelize.INTEGER
}
I Am using belongsToMany of sequelize and creating a third table name UserLocation where I have mentioned belongsToMany for both User and Location which is as below:
User.belongsToMany(Location, {
through: 'UserLocation'
});
Location.belongsToMany(User, {
through: 'UserLocation'
});
My requirement is to get all the locations for a given user id. My Code is as follows:
var param = req.body;
var options = {};
if (param.where) {
options.where = param.where;
}
options.include = [{
model: User //User Model
}, {
model: Location //Location Model
}];
//Here userLocation refers to UserLocation Schema
userLocation.findAll(options).then(function (response) {
//Some Logic
}).catch(function (err) {
//Error handling
});
While executing the above code, I getting the following error:
User Model is not associated with UserLocation Model.
I am unable to understand why I am getting the following error. Can somebody help me out with this?
You can use this for getting all the locations of a given user;
User
.findOne({
"where": {
"id": param.where
},
"include": [Location]
})
.then(function(user) {
// should get this user
console.log(user);
// should get all locations of this user
console.log(user.Locations);
})
.catch(function(error) {
// error handling
});