How to do a query in Sequelize? - javascript

I've an existing Postgres database. Throught sequelize-auto, I generated the models for the existing database. For example, let's look at the tc_devices table (tc_devices.js):
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('tc_devices', {
id: {
autoIncrement: true,
autoIncrementIdentity: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING(128),
allowNull: false
},
uniqueid: {
type: DataTypes.STRING(128),
allowNull: false,
unique: "tc_devices_uniqueid_key"
},
lastupdate: {
type: DataTypes.DATE,
allowNull: true
},
positionid: {
type: DataTypes.INTEGER,
allowNull: true
},
groupid: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'tc_groups',
key: 'id'
}
},
attributes: {
type: DataTypes.STRING(4000),
allowNull: true
},
phone: {
type: DataTypes.STRING(128),
allowNull: true
},
model: {
type: DataTypes.STRING(128),
allowNull: true
},
contact: {
type: DataTypes.STRING(512),
allowNull: true
},
category: {
type: DataTypes.STRING(128),
allowNull: true
},
disabled: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false
}
}, {
sequelize,
tableName: 'tc_devices',
schema: 'public',
timestamps: false,
indexes: [
{
name: "tc_devices_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
{
name: "tc_devices_uniqueid_key",
unique: true,
fields: [
{ name: "uniqueid" },
]
},
]
});
};
In database.js, I connect to the database:
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize(database, user, password, {
host,
port,
dialect: 'postgres',
logging: false
})
async function db_connection(){
try{
await sequelize.authenticate();
console.log('Connection has been estabilished successfully.');
}catch{
console.log('Unable to connect to the database.');
}
}
db_connection()
How can I do a simple query on the tc_devices table? what should I import in database.js? in tc_devices I export function(sequelize, DataTypes)... but I can't understand how to do a query in database.js with this function...could you help me? thank you so much.

You need to register all models and their associations before executing the first query with these models. Look at my answer here.
As soon as you do it you can execute queries like this:
// assuming db already stores all model definitions
const allRecords = await db.tcDevices.findAll({})

Related

Creating table from sequelize-auto with init-mode.js and js files

I made init-models.js, testtbl.js and usertbl.js with sequelize-auto in ubuntu from mysql table structure.
Command I executed in ubuntu shell:
$ sequelize-auto -o "./models" -h localhost -u foo -p bar -x password -e mysql
And I saw that Sequelize-auto made files models/init.js and models/testtbl.js, usertbl.js
Unfortunately, I blew up mysql table testtbl, usertbl entirely and I want to recover it with testtbl.js and usertbl.js
I want to know sequelize command that making table testtbl and usertbl on mysql with models/init-models.js, models/testtb.js and usertbl.js
I can show init-model.js, testtbl.js and usertbl.js
init-model.js :
var DataTypes = require("sequelize").DataTypes;
var _testtbl = require("./testtbl");
var _usertbl = require("./usertbl");
function initModels(sequelize) {
var testtbl = _testtbl(sequelize, DataTypes);
var usertbl = _usertbl(sequelize, DataTypes);
return {
testtbl,
usertbl
};
}
module.exports = initModels;
module.exports.initModels = initModels;
module.exports.default = initModels;
testtbl.js :
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('testtbl', {
idx: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
val: {
type: DataTypes.STRING(45),
allowNull: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}, {
sequelize,
tableName: 'testtbl',
timestamps: false,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "idx" },
]
},
]
});
};
usertbl.js :
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('usertbl', {
uididx: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
uid: {
type: DataTypes.STRING(45),
allowNull: false,
unique: "uid_UNIQUE"
},
passwd: {
type: DataTypes.STRING(45),
allowNull: true
},
devicename: {
type: DataTypes.STRING(45),
allowNull: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}, {
sequelize,
tableName: 'usertbl',
timestamps: false,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "uididx" },
]
},
{
name: "uid_UNIQUE",
unique: true,
using: "BTREE",
fields: [
{ name: "uid" },
]
},
]
});
};

Node JS API Sequelize PostgreSQL UUID as primary key return error "column Nan does not exist"

I'm working on a REST API for the backend of a simple e-commerce app using Node JS, PostgreSQL and Sequelize, and I'm facing an issue with Sequelize when I try to add a product to the shopping cart. It returns an error "column Nan does not exist"
Initially I was using Integer for the user Id as the primary key, then I changed for UUID to better suit the purpose.
The code I'm using for the models and migrations is the following:
//User model
export default (sequelize, DataTypes) => {
const User = sequelize.define(
'User',
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true,
unique: true,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: {
name: 'user_email',
msg: 'A user with this email already exists.'
}
},
},
User.associate = models => {
User.hasOne(models.Cart, {
foreignKey: 'userId',
as: 'cart',
onDelete: 'cascade'
});
};
User.associate = models => {
User.hasMany(models.Order, {
foreignKey: 'userId',
as: 'orders',
onDelete: 'cascade'
});
};
return User;
};
//User migration
export const up = (queryInterface, Sequelize) =>
queryInterface.createTable('Users', {
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
unique: true,
},
name: {
allowNull: false,
type: Sequelize.STRING
},
password: Sequelize.STRING,
email: {
allowNull: false,
type: Sequelize.STRING,
unique: true
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('now')
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('now')
},
});
export const down = queryInterface => queryInterface.dropTable('Users');
Cart model
export default (sequelize, DataTypes) => {
const Cart = sequelize.define('Cart', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true,
},
userId: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false
},
cartItem: {
type: DataTypes.TEXT,
allowNull: false,
get(value) {
return JSON.parse(this.getDataValue(value));
},
set(value) {
this.setDataValue('cartItem', JSON.stringify(value));
}
}
});
Cart.associate = models => {
Cart.belongsTo(models.User, {
foreignKey: 'userId',
as: 'owner'
});
};
return Cart;
};
Cart migration
export const up = (queryInterface, Sequelize) =>
queryInterface.createTable('Carts', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
},
userId: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false
},
cartItem: {
type: Sequelize.TEXT,
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('now')
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.fn('now')
}
});
export const down = queryInterface => queryInterface.dropTable('Carts');
Code to handle the add to cart:
addToCart() {
return this.asyncWrapper(async (req, res) => {
const { body, user } = req;
body.userId = user.id;
const cart = await this.service.addToCart(body);
this.sendResponse(res, cart, undefined, 201);
});
}
Add to cart service
async cart(userId, options = {}) {
const cart = await super.find({ userId }, options);
return cart;
}
async addToCart(data, options) {
const { userId, productId, qty } = data;
const [result] = await this.model.findOrCreate({
where: { userId: +userId },
defaults: { cartItem: new CartItem() }
});
const cartData = JSON.parse(result.dataValues.cartItem);
const cartItem = new CartItem(cartData);
const product = await ProductService.getById(productId, { plain: true });
ExceptionHandler.throwErrorIfNull(product);
const cart = cartItem.addToCart(product, qty);
result.cartItem = cart;
result.save();
return result;
}
The SQL query generated by Sequelize is the following:
SELECT "id","userId","cartItem","createdAt","updatedAt" FROM "Carts" AS "Cart" WHERE "Cart"."userId" = NaN LIMIT 1;
The goal is to use UUID as primary key in the database.
This issue started when I changed the Datatype from Integer for UUID and I can't see what is wrong with the code.
Any advice on how to solve this?
Sequelize version: "^5.21.9" with "pg": "^8.2.0" and "pg-hstore": "^2.3.3".
If you switched a data type from INTEGER to UUID you shouldn't try to convert UUID-string to a number doing where: { userId: +userId }.
Pass userId as is:
where: { userId }

Sequelize - foreign key on create include returns null

The foreign key returns null when inserted using create include, but the rest of data is saved from the passed object.
Here is my transaction model:
module.exports = (sequelize, DataTypes) => {
const Transaction = sequelize.define('transactions', {
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true
},
receiptNumber: {
type: DataTypes.TEXT,
allowNull: true
},
supCustID: {
type: DataTypes.INTEGER,
allowNull: true
},
userID: {
type: DataTypes.INTEGER,
allowNull: true
},
type: {
type: DataTypes.TEXT,
allowNull: true
},
status: {
type: DataTypes.INTEGER,
allowNull: true
},
remarks: {
type: DataTypes.TEXT,
allowNull: true
},
createdAt: {
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
},
updatedAt: {
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
}
}, {
tableName: 'transactions'
});
Transaction.associate = models => {
Transaction.Order = Transaction.hasMany(models.Order, {
as: 'Orders',
foreignKey: 'transaction_id'
})
Transaction.SupCust = Transaction.belongsTo(models.SupCust, {
as: 'SupCust',
foreginKey: 'supCustID'
})
Transaction.User = Transaction.belongsTo(models.User, {
as: 'User',
foreginKey: 'userID'
})
}
return Transaction;
};
Orders Model:
/* jshint indent: 1 */
module.exports = (sequelize, DataTypes) => {
const Order = sequelize.define('orders', {
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true
},
transaction_id: {
type: DataTypes.INTEGER,
allowNull: true
},
itemID: {
type: DataTypes.TEXT,
allowNull: true
},
qty: {
type: DataTypes.INTEGER,
allowNull: true
},
itemCost: {
type: DataTypes.REAL,
allowNull: true
},
discount: {
type: DataTypes.REAL,
allowNull: true
},
totalAmount: {
type: DataTypes.REAL,
allowNull: true
}
}, {
tableName: 'orders',
timestamps: false,
hooks: {
afterValidate: (Order) => {
console.log(Order)
},
}
});
Order.associate = models => {
Order.belongsTo(models.Transaction, {
as: 'Transactions',
foreignKey: 'transaction_id'
})
Order.belongsTo(models.ItemList, {
as: 'Items',
foreignKey: 'itemID'
})
}
return Order;
};
Code to execute insert data:
return await models.Transaction
.findOne({ where: { id: values.id || -1 } })
.then(async function (obj) {
if(obj) { // update
return await obj.update(values, {individualHooks: true});
}
else { // insert
const {id, ...payload} = values
return await models.Transaction.create(payload, {
include: [{
association: models.Transaction.Order
}],
});
}
})
Results from console:
Executing (default): INSERT INTO `transactions` (`id`,`receiptNumber`,`supCustID`,`userID`,`type`,`createdAt`,`updatedAt`) VALUES ($1,$2,$3,$4,$5,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
Executing (default): INSERT INTO `orders` (`id`,`transaction_id`,`itemID`,`qty`,`itemCost`) VALUES ($1,$2,$3,$4,$5);
Console log from hooks on orders model:
dataValues:
{ id: null,
itemID: 1008,
itemCost: '2',
qty: '1',
transaction_id: null },
Why is this always null? what am i missing something?
Solved this by adding autoincrement property on my transaction model.
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true,
autoIncrement: true
}

Sequelize assocation to same table

I have a table called documents that has a column called parentId which is a reference to another document record.
With my current code i'm getting the error
insert or update on table "documents" violates foreign key constraint "documents_parentId_fkey"
documents migration
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('documents', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4
},
parentId: {
allowNull: true,
type: Sequelize.UUID,
references: {
model: 'documents',
key: 'id'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
lastUpdatedAt: {
allowNull: false,
type: Sequelize.DATE
},
lastUpdatedBy: {
allowNull: false,
type: Sequelize.UUID
}
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('documents')
}
}
document model
'use strict'
module.exports = (sequelize, DataTypes) => {
const document = sequelize.define('document', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
parentId: {
allowNull: true,
type: DataTypes.UUID,
references: {
model: 'documents',
key: 'id'
}
},
lastUpdatedBy: {
allowNull: false,
type: DataTypes.UUID
}
},
{
updatedAt: 'lastUpdatedAt'
})
document.associate = function (models) {
document.belongsTo(models.document, { foreignKey: 'parentId' })
}
return document
}
How do you properly do associations to the same table?
I have a self referencing table configured with the constraints: false setting.
MyModel.belongsTo(MyModel, {
as: 'parentMyModel',
foreignKey: 'parentId',
constraints: false,
});
Looks like the constraint is valid (and a good one). My payload that I was submitting had a parent uuid which didn't actually reference any document with that id.
So my code was right, the data I was submitting was wrong.

Sequelize bulkCreate not including newly added columns

I'm having difficulty understanding why bulkCreate will not include my two newly created columns, perhaps it's the migration?
My new migration is as follows:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
queryInterface.addColumn('users', 'brand_id', {
allowNull: true,
type: Sequelize.INTEGER,
defaultValue: null,
});
queryInterface.addColumn('users', 'store_id', {
allowNull: true,
type: Sequelize.INTEGER,
defaultValue: null,
});
return true;
},
down: (queryInterface, Sequelize) => {
queryInterface.removeColumn('users', 'brand_id');
queryInterface.removeColumn('users', 'store_id');
return true;
}
};
I have a helper function for creating multiple users for the purpose of testing that looks something like this:
const properties = { brand_id: 123 };
const user = [];
users.push(Object.assign({}, {
name: chance.last(),
email: chance.email(),
password,
access_key: uuid(),
}, properties));
const newUsers = await models.user.bulkCreate(users, { returning: true, logging: console.log });
The output of the logging is:
INSERT INTO "users" ("id","name","email","password","access_key","created_at","updated_at") VALUES (DEFAULT,'Valente','letubdo#iwefa.fm','$2a$08$B5riQzA82ChwuH1q8HpGxOBK2uQj2m.BiHcEjytiox5yD.8u1fT5W','e62bf96c-0117-490f-9c80-b60e406238b0','2018-09-25 18:30:04.666 +00:00','2018-09-25 18:30:04.666 +00:00') RETURNING *;
You'll see that brand_id is completely ignored in the query, even if I change the following:
users.push(Object.assign({}, {
name: chance.last(),
email: chance.email(),
password,
access_key: uuid(),
brand_id: 123,
}, properties));
Any idea what could be wrong?
It turns out I did not add the two new columns to the user model:
'use strict';
module.exports = (sequelize, DataTypes) => {
var user = sequelize.define('user', {
name: {
allowNull: false,
type: DataTypes.STRING
},
email: {
allowNull: false,
type: DataTypes.STRING
},
password: {
allowNull: false,
type: DataTypes.STRING
},
access_key: {
allowNull: false,
type: DataTypes.STRING
},
brand_id: {
allowNull: true,
true: DataTypes.INTEGER,
},
store_id: {
allowNull: true,
true: DataTypes.INTEGER,
}
}, {
underscored: true,
});
return user;
};

Categories

Resources