I was hoping to get some help. I just started using Postgres with my Node applications and am curious to find out how to go about dealing with models and model methods. What is the best practice when working with Node and Postgres in regards to models and methods? I was looking around and all I could find is something called Objection, but is it absolutely necessary I take that route?
Ideally I would like to have a model.js file for each component but I have not seen them used when dealing with Postgres + Node.
Any help is greatly appreciated. Thanks guys, hope you all had a great Thanksgiving!
Assuming that viewer can understand basic javascript modules and that the codes are mostly self explanatory
This is my model.js file
module.exports = ({
knex = require('./connection'),
name = '',
tableName = '',
selectableProps = [],
timeout = 1000
}) => {
const query = knex.from(tableName)
const create = props => {
delete props.id
return knex.insert(props)
.returning(selectableProps)
.into(tableName)
.timeout(timeout)
}
const findAll = () => {
return knex.select(selectableProps)
.from(tableName)
.timeout(timeout)
}
const find = filters => {
return knex.select(selectableProps)
.from(tableName)
.where(filters)
.timeout(timeout)
}
const update = (id, props) => {
delete props.id
return knex.update(props)
.from(tableName)
.where({
id
})
.returning(selectableProps)
.timeout(timeout)
}
const destroy = id => {
return knex.del()
.from(tableName)
.where({
id
})
.timeout(timeout)
}
return {
query,
name,
tableName,
selectableProps,
timeout,
create,
findAll,
find,
update,
destroy
}
}
This is my controller.js file
const model = require('./model');
const user = model({
name: "users",
tableName: "tbl_users",
});
const getAllUsers = async (req, res, next)=>{
let result = await user.findAll();
res.send(result);
}
module.exports = { getAllUsers }
And Lastly a the connection.js file
const knex = require('knex')({
client: 'pg',
connection: {
host: 'YOUR_HOST_ADDR',
user: 'YOUR_USERNAME',
password: 'YOUR_PASS',
database: 'YOUR_DB_NAME'
},
pool: {
min: 0,
max: 7
}
});
module.exports = knex;
Related
Good evening.
I'm building an Express REST API using SQLite, with Sequelize being my ORM of choice.
I was working with an existing database, so I used a package called sequelize-auto in order
to generate my models.
Problem is, Sequelize for some reason won't see my database, a .db file, or won't detect the table, despite being clearly defined. The problem occurs in this block of code:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('expenserdb', 'user', 'pass', {
dialect: 'sqlite',
host: '../database/expenserdb.db'
});
const initModels = require('../models/init-models');
const models = initModels(sequelize);
module.exports = class dbService {
editUserName(newName) {
models.User.update({Name: newName}, {
where: {
UserId: 1
}
})
.catch((err) => {console.log(err)});
}
}
This is my dbService.js file, and as you can see, the database is clearly defined, with the name, location and everything being correct. Despite all of this, I'm still getting:
Error: SQLITE_ERROR: no such table: User {errno: 1, code: 'SQLITE_ERROR', sql: 'UPDATE `User` SET `Name`=$1 WHERE `UserId` = $2'
This service is being injected into my controller via awilix, and the method is called inside the controller:
const container = require("../containerConfig");
const dbService = container.resolve("dbService");
exports.runNameChange = async (req) => {
const newName = JSON.stringify(req.body.name);
const result = await dbService.editUserName(newName);
return result;
};
And in turn, the controller method is ran when this endpoint is hit:
app.post('/updateuser', async function(req, res) {
const result = await userController.runNameChange(req);
res.status(200).send(String(result));
});
Also, the dboptions.json file:
{
"storage":"./database/expenserdb.db"
}
I'm new to Node, Express, and Sequelize in general. I might have missed something crucial, but I can't seem to realize what. Help is greatly appreciated.
Update: just figured it out, you need the FULL path and not the relative path in the
verbose constructor, as such:
const sequelize = new Sequelize('expenserdb', 'user', 'pass', {
dialect: 'sqlite',
storage: 'E:/desktopshortcuts/yahalom/expenser/expenser-server/database/expenserdb.db'
});
Please am new to Nodejs but am trying to insert a data into my database using sequelize but am getting Cannot read property .create of undefined.
This is my index.js file
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.DB,
config.USER,
config.PASSWORD,
{
host: config.HOST,
dialect: config.dialect,
operatorsAliases: false,
pool: {
max: config.pool.max,
min: config.pool.min,
acquire: config.pool.acquire,
idle: config.pool.idle
}
});
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
// db[model] = model
db.User = model
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db;
This is my Model/User.js File
module.exports = (sequelize, DataTypes) => {
sequelize.define('User', {
hmtec_email: {
type: DataTypes.STRING,
unique: true
},
hmtec_password: DataTypes.STRING
})
This is my Controllers/AuthController.js File
const {User} = require ('../models/User')
module.exports = {
async register (req, res) {
try {
const user = await User.create(req.body)
res.send(user.toJSON())
} catch (err) {
console.log(err);
res.status(400).send({
error: 'Email already in Use'
})
}
}
I don't know what wrong with the code, I dont know why am getting that error of .create is undefined
I think your problem is in the last file .. AuthController.js
const {User} = require ('../models/User')
You are using the Es6 new destruction assignment
More Info here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Normally you should define your variable without the brackets
That mean you got all of the variable available.
But adding the brackets means that you want to get the child of the object, this child is named user .. and then name the variable also as user
and search these info
From the require file after the equal.
But in your user file .. you are exporting a function .. that does not have any child named user
Thus undefined
Better alternative is to use Classes
More info here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
So in user model
// Inside your function you need to use sequalize module , iam not familar with it but you must require it to use it
const Sequelize = require('sequelize');
// Define the Class
class user {
// add the name you want to use for the function - here I used create so the other code also work - also I inserted async because this is asynchronous and also I removed the sequalize from parameters because you don't need it now after it is required above.
async create (DataTypes) => {
await Sequelize.define('User', {
hmtec_email: {
type: DataTypes.STRING,
unique: true
},
hmtec_password: DataTypes.STRING
})
}
module.exports = user;
Now when you require the file in Authcontroller , remove the brackets
const User = require ('../models/User')
and now you can use User.create(YOUR_DATA_VARIABLE);in your authController.js
and if there is any other functions inside this class you also can use them in the same manner.
I hope this fix your problem.
I have this query to display in a table on frontend so I used paginate which is working fine
tableSchema.statics.getn = (query, options) => {
return mongoose.model(MODEL_NAME).paginate(query, options);
};
But when I am trying to perform search query then I am unable to perform paginate on that. Is there any way to send response as paginated form to all the searched queries
I tried following code
tableSchema.statics.search = query => {
const Id = Number(query);
const isNumeric = value => /^\d+$/.test(value);
if (!isNumeric(query)) {
if (query.includes("#")) {
const regex = new RegExp(query, "i");
return mongoose.model(MODEL_NAME).find({ "recipies.to": regex }).paginate(query);
}
return mongoose.model(MODEL_NAME).find({ "temp.name": query });
}
return mongoose.model(MODEL_NAME).find({ recipies: { Id } });
};
It is throwing me error that paginate is not a function. I tried storing find query result in object then performed paginate still it was not working.
I am using "mongoose-paginate-v2" for pagination
Hi I think you missed to add pagination pluging in model section.
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const mySchema = new mongoose.Schema({
/* your schema definition */
});
mySchema.plugin(mongoosePaginate);
const myModel = mongoose.model('SampleModel', mySchema);
myModel.paginate().then({}); // Usage
You need to add mongoosePaginate in model as plugin.
let options = {
sort: { createdOn: 1 },
page: 1,
limit: 10
};
ModelName.paginate({ 'recipies.to': 'value' }, options, function (err, result) {
if (err) {
console.log(err);
} else {
// Here you will get paginate array please console and check
console.log(result);
}
How can I get the number of rows (without any filter)?
I've tried this User.fetch().count() and User.count(), but I get these errors respectively:
TypeError: User.fetch is not a function
AssertionError: expected { Object (_bitField, _fulfillmentHandler0, ...) } to equal 0
Here's my model:
let bookshelf = require('../config/database');
require('./role');
var User = bookshelf.Model.extend({
tableName: 'users',
role: function() {
return this.hasOne(Role);
}
});
module.exports = bookshelf.model('User', User);
try this:
const knex = require("knex")(require("./knexfile").development);
const Bookshelf = require("bookshelf")(knex);
const User = Bookshelf.Model.extend({
tableName: "user",
idAttribute: "userid"
});
knex.migrate.latest().then(_ => {
User.forge().count().then(ret => {
console.log(ret);
process.exit(0);
});
});
the output should be:
[sombriks#sephiroth sample-knex-bookshelf]$ node index.js
Knex:warning - sqlite does not support inserting default values. Set the `useNullAsDefault` flag to hide this warning. (see docs http://knexjs
.org/#Builder-insert).
3
[sombriks#sephiroth sample-knex-bookshelf]$
please take a look at this repo if you want a more detailed info.
I'm working on a backend that is utilizing Node and Sequelize ORM. The database being used is PostgreSQL. I've used hasOne() in the code before and it worked great all the createAssociation(), getAssociation() methods from the hasOne() relationship worked when I used it before. However for some reason it is giving me a problem now.
index.js
const Connection = new Sequelize(
'postgres',
'postgres',
null,
{
dialect: 'postgres',
host: '192.168.99.100',
port: '5432',
}
);
const ModelSeven = Connection.define('modelSeven', ModelSevenSchema),
ModelFive = Connection.define('modelFive', ModelFiveSchema),
ModelOne = Connection.define('modelOne', ModelOneSchema),
ModelSix = Connection.define('modelSix', ModelSixSchema),
ModelThree = Connection.define('modelThree', ModelThreeSchema),
ModelFour = Connection.define('modelFour', ModelFourSchema),
ModelOne.hasOne(ModelThree); // Defines hasOne() relationship
ModelOne.hasOne(ModelFour); // Defines hasOne() relationship
ModelSix.belongsToMany(ModelOne, {through: 'Pivot'});
ModelOne.belongsToMany(ModelSix, {through: 'Pivot' });
ModelOne.belongsTo(ModelSeven);
ModelThree.hasMany(ModelFive);
ModelFour.hasMany(ModelFive);
export default Connection;
utilize.js
import DB from './somePathToIndex.js';
//GraphQL resolve function
async resolve (root, args, context) {
//creates ModelOne
var ModelOne = await DB.models.ModelOne.create({
value: args.value,
valueTwo: args.valueTwo
});
// attempts to createModelThree/createModelFour from hasOne() relationship
var ModelThree = await ModelOne.createModelThree({});
var ModelFour = await ModelOne.createModelFour({});
// Maps through value array finding the modelFive with and id and adding
// it to modelThree via hasMany() relationship
args.value.map(async (id, key) => {
var ModelFive = await DB.models.ModelFive.findAll({
where: {
id: id
}
});
await ModelThree.addModelFive(ModelFive);
});
// Maps through value array finding the modelFive with and id and adding
// it to modelFour via hasMany() relationship
args.valueTwo.map(async (id, key) => {
var ModelFive = await DB.models.ModelFive.findAll({
where: {
id: id
}
});
await ModelFour.addModelFive(ModelFive);
});
return ModelOne;
}
The problem is that when node hits the line:
var ModelThree = await ModelOne.createModelThree({});
var ModelFour = await ModelOne.createModelFour({});
Gives me the following error:
"errors": [
{
"message": "ModelOne.createModelThree is not a function",
"locations": [
{
"line": 38,
"column": 3
}
]
}
]
This error is saying that the hasOne() relationship method create[Association]() is not a function. I cannot really tell why this is. If you know why please let me know.