Sequelize: Modify output of date timestamp using Getters - javascript

I need to convert my signup_at timestamp to a certain format each time it's selected from the database.
I want to use a getter for this, but it doesn't appear to be returning the modified data. It continues to return the same date object stored in the database.
var moment = require("moment");
var Referral = sequelize.define("referral", {
id: {
allowNull: false,
type: DataTypes.CHAR(24),
unique: true,
primaryKey: true
},
active: {
allowNull: false,
type: DataTypes.BOOLEAN,
defaultValue: true
},
name: {
allowNull: true,
type: DataTypes.STRING
},
method: {
allowNull: true,
type: DataTypes.STRING
},
signup_at: {
allowNull: false,
type: DataTypes.DATE,
get: function() {
return moment(this.getDataValue("signup_at")).format("MM/DD/YYYY");
}
}
});
Referral.findAll({
where: {
active: true
},
raw: true
}).then(function(referrals) {
console.log(referrals);
});

Try the following code
Referral.findAll({
where: {
active: true
},
raw: false
}).then(function (referrals) {
referrals.forEach(function (referral, index, array) {
var value = referral.get();
console.log(value);
});
});
It seems raw = true won't use the getter function.
You may make raw false and call the get explicitly.

Related

How to update immutable values in mongodb?

I have collection like this.
const Device: Schema = new Schema(
{
location: {
type: String,
required: true,
},
macAddress: {
type: String,
required: true,
immutable: true,
},
ip: {
type: String,
required: true,
immutable: true,
},
},
{
timestamps: true,
versionKey: false,
collection: 'Device',
}
);
I want to update immutable fields with my endpoints and i use this function and doesnt work.
Device.findOneAndUpdate(
{ _id: req.params.mdeviceId },
{ $set: { macAddress: req.body.macAddress, ip: req.body.ip},
{ new: true, upsert: true }
);
How can i update this specific fields?
I would guess req.params.mdeviceId is a string and needs to be casted to ObjectId, this is not related to the immutable property as you are providing the new flag which allows to bypass the schema protection, try using this:
Device.findOneAndUpdate(
{ _id: new mongoose.Types.ObjectId(req.params.mdeviceId) },
{ $set: { macAddress: req.body.macAddress, ip: req.body.id},
{ new: true, upsert: true }
);

Sequelize - Build dynamic where clause with 'Op.or'

I had this code block working with Sequelize v5. But since switching to v6, it seems to be erroring out. I am getting the error: Error: Invalid value { customer_id: 'dg5j5435r4gfd' }.
And here is the code that creates the where condition block:
let whereBlock = {
deleted_at: null,
};
if (args.includeCore) {
if (customerID !== 'all') {
// whereBlock[Op.or] = [
// { customer_id: customerID },
// { customer_id: coreCustomerID },
// ];
whereBlock[Op.or] = [];
whereBlock[Op.or].push({
customer_id: customerID,
});
whereBlock[Op.or].push({ customer_id: coreCustomerID });
}
} else {
whereBlock.customer_id = customerID;
}
I was using the commented code. And then I tried the code below that. Both are producing the same error. But when I remove all that code from the if block and just put in whereBlock.customer_id = customerID;, then it works fine. So I know the issue is how I am constructing the where condition.
Update: As requested, here is my Sheets model where the where clause is being run on.
'use strict';
export default (sequelize, DataTypes) => {
return sequelize.define(
'Sheet',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
},
sheet_name: {
type: DataTypes.STRING,
isAlphaNumeric: true,
required: true,
allowNull: true,
len: [3, 80],
},
sheet_file_name: {
type: DataTypes.STRING,
unique: true,
isAlphaNumeric: true,
required: false,
allowNull: true,
},
brand_name: {
type: DataTypes.STRING,
unique: false,
isAlphaNumeric: true,
required: false,
allowNull: true,
},
customer_id: {
// fk in customers table
type: DataTypes.TINYINT(2).UNSIGNED,
required: true,
allowNull: false,
},
chemical_id: {
// fk in loads table
type: DataTypes.SMALLINT.UNSIGNED,
required: true,
allowNull: false,
},
load_id: {
// fk in loads table
type: DataTypes.SMALLINT.UNSIGNED,
required: true,
allowNull: false,
},
active: {
type: DataTypes.BOOLEAN,
required: true,
allowNull: false,
defaultValue: true,
},
created_at: {
type: DataTypes.DATE,
},
updated_at: {
type: DataTypes.DATE,
},
deleted_at: {
type: DataTypes.DATE,
},
},
{
underscored: true,
paranoid: false,
}
);
};
And in my index I have this to associate sheets with customers: db.Sheet.belongsTo(db.Customer);
Also here is the full code where the whereBlock is used, if that helps:
const files = await db.Sheet.findAll({
raw: true,
attributes: [
'sheet_name',
'sheet_file_name',
['brand_name', 'brand'],
'updated_at',
'active',
[Sequelize.col('Chemical.name'), 'chemical'],
[Sequelize.col('Load.value'), 'load'],
],
include: [
{
model: db.Load.scope(null),
required: true,
as: 'Load',
attributes: ['value'],
},
{
model: db.Chemical.scope(null),
required: true,
as: 'Chemical',
attributes: ['name'],
},
],
// model: model,
where: whereBlock,
order: [['active', 'DESC']],
});
TLDR: So here is what it comes down to:
whereBlock = {
deleted_at: null,
customer_id: customerID,
// [Op.or]: [
// { customer_id: customerID },
// { customer_id: coreCustomerID },
// ],
};
That code above works, but the commented code errors out with: Error: Invalid value { customer_id: '123456' }
OK, this is very weird. But I finally figured out the issue!! Was not something I would have thought of, just found it by chance. It was the way I was importing Op from sequelize.
import Op from 'sequelize';
So apparently, that Op object has another object inside it called Op. So when I call my [Op.or], I instead need to do this: [Op.Op.or].
I did try switching my import to import Op.Op from 'sequelize'; and that caused errors. Anyone know how I can properly import the inner object?
Update
OK, so apparently in my other DB files, I was doing the import differently.
export default (db) => {
const Op = db.Sequelize.Op;
That method works to pull in the correct Op object. So there you go. Hopefully this nightmare issue helps someone else in the future.

Sequelize: Foreign key declared, but does not appear in the table

I'm new to using Sequelize and for that I strictly follow the documentation here. It is written that we must use hasOne(), hasMany(), belongsTo() in order to add automatically the foreign keys. In my situation: I have a Category and a FAQ model, defined so:
Category.js
const { Sequelize } = require('sequelize');
const sequelize = require('../database/connection');
const Category = sequelize.define('Category', {
id: {
type: Sequelize.DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
},
categoryShop_id: {
type: Sequelize.DataTypes.UUID,
allowNull: true
},
name: {
type: Sequelize.DataTypes.STRING,
allowNull: false
},
active: {
type: Sequelize.DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true
},
parent_id: {
type: Sequelize.DataTypes.INTEGER,
allowNull: true
}
});
Category.associate = (models) => {
Category.hasMany(models.faqs, {
onDelete:'CASCADE',
onUpdate:'CASCADE'
});
};
module.exports = Category;
Faq.js
const { Sequelize } = require('sequelize');
const sequelize = require('../database/connection');
const Faq = sequelize.define('Faq', {
id: {
type: Sequelize.DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
},
question: {
type: Sequelize.DataTypes.TEXT,
allowNull: false
},
answer: {
type: Sequelize.DataTypes.TEXT,
allowNull: false
},
product_id: {
type: Sequelize.DataTypes.STRING,
allowNull: true
},
active: {
type: Sequelize.DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true
}
});
Faq.associate = (models) => {
Faq.belongsTo(models.categories, {
foreignKey: {
name: 'category_id',
allowNull: true
}
});
};
module.exports = Faq;
The migrations run without any errors, but I don't see the added columns to the table. What is the reason for this?
Your confusing model and migration code. Your migrations are ok, but lack the right foreign key columns for your associations.
Your association code looks ok but it belongs in your model.
Look at https://sequelizeui.app/ for some example code.

How to pass object as a data type to a data model in sequilize?

I need to pass something that is not a primitive to the data type.
I am constructing something like this to send to the create method:
const p2 = {
location_model: {
latitude: lat,
longitude: lng
},
establishment_id: createdEstablishment.id
}
As you can see the establishment_id is of type Integer but the location_model is an object
This is my model
module.exports = {
up: (queryInterface, DataTypes) => {
return queryInterface.createTable('EstablishmentLocation', {
location_model: {
type: // need some datatype that accept's an object of that type
allowNull: false,
references: {
model: 'Location',
key: 'id',
},
},
establishment_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'Establishment',
key: 'id',
},
},
createdAt: {
allowNull: false,
type: DataTypes.STRING,
defaultValue: DataTypes.STRING,
},
updatedAt: {
allowNull: false,
type: DataTypes.STRING,
defaultValue: DataTypes.STRING,
}
});
},
down: (queryInterface) => {
return queryInterface.dropTable('EstablishmentLocation');
}
};
My question is, how can I pass an object to a data type in sequilize?
The type you provide in the model are the types defined in the database you use. If you are using postgresql, you can use DataTypes.JSON as the type.
If not, to save object, you can JSON.stringify the object and pass it as a string.

Sequelize association not syncing with model definition

'use strict';
module.exports = (sequelize, type) => {
const article_comment = sequelize.define('article_comments', {
// attributes
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true
},
positive_rating:{
type: type.INTEGER,
allowNull: false
},
negative_rating:{
type: type.INTEGER,
allowNull: false
},
comment:{
type: type.STRING,
allowNull: false
},
updatedAt:{
type: type.STRING,
allowNull: false
},
createdAt:{
type: type.STRING,
allowNull: false
},
}, {});
article_comment.associate = function(models) {
// associations can be defined here
article_comment.hasMany(models.article_comments_user_ratings,{foreignKey:'comment_id'});
article_comment.hasMany(models.article_replies,{foreignKey:'comment_id'});
};
return article_comment;
};
And my rating for comments
'use strict';
module.exports = (sequelize, type) => {
const article_comments_user_ratings = sequelize.define('article_comments_user_ratings', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: type.INTEGER
},
rating:{
type: type.BOOLEAN,
allowNull: false
},
createdAt: {
allowNull: false,
type: type.DATE
},
updatedAt: {
allowNull: false,
type: type.DATE
}
}, {});
article_comments_user_ratings.associate = function(models) {
// associations can be defined here
article_comments_user_ratings.belongsTo(models.article_comments)
};
return article_comments_user_ratings;
};
However, when I use the findOrCreate method, it only does INSERT INTO "article_comments_user_ratings" ("id","rating","createdAt","updatedAt"). Which obviously is failing because In the database I also have the additional columns of user_id and comment_id for the article_comments_user_ratings table.
This isn't making any sense because with the sync() function, prior to moving to migrations, it was working.
I don't know what to do?
I fixed this issue by defining the associations after defining the model.
Example:
const User = UserModel(sequelize, Sequelize)
const Comment = CommentsModel(sequelize, Sequelize)
User.hasMany(UserCommentRating,{foreignKey:'user_id'})
Comment.hasMany(UserCommentRating,{foreignKey:'comment_id'})
It seems that the assocations inside the model is deprecated.

Categories