:Sequelize how set returned data order - node.js

I've issues set the returned data order of a findAll query with limit and offset, i'm using example code found in the documentation: order: 'group DESC' but it throw an error saying:
Error: SQLITE_ERROR: near "group": syntax error
Here is the complete function.
A_Model.findAll({
offset:req.query.page * req.query.rows - req.query.rows,
limit :req.query.rows // TODO: Of course, I put the trailing comma here ;)
// TODO: order: 'group DESC'
})
.success(function (docs) {
response_from_server.records = count;
response_from_server.page = req.query.page;
response_from_server.total = Math.ceil(count / req.query.rows);
response_from_server.rows = [];
for (item in docs) {
response_from_server.rows.push({
id :docs[item].id,
cell:[
docs[item].group,
docs[item].description,
docs[item].path,
docs[item].value
]
});
}
// Return the gathered data.
res.json(response_from_server);
})
.error(function (error) {
logger.log('error', error);
});
Thanks in advance.

The "order"-string you give to the findAll method is not parsed in Sequelize, only escaped to prevent SQL-injections. "group" is a reserved keyword in most some SQL-dialects, so the query fails to run.
To make it work simply put the "group" column into `'s, like this:
A_Model.findAll({
offset:req.query.page * req.query.rows - req.query.rows,
limit :req.query.rows,
order: '`group` DESC'
})

Related

Javascript promise to iterate/include dynamic number of Arguments

I'm using the mssql npm module (with Tedious driver) to read/write to Azure Sql database from my node Server. https://www.npmjs.com/package/mssql
All the examples I've found provide an hardcoded example of the query whether to read or write records, like this:
var insertRecordIntoTable = function (callback) {
sql.connect(dbConfig).then(pool => {
return pool.request()
.input('ID', sql.Int, 210)
.input('Name', sql.NVarChar, "John Doe")
.input('EmailAddress', sql.NVarChar, "test#test.com")
.query("INSERT INTO Accounts (ID, Name, EmailAddress) VALUES (#ID, #Name, #EmailAddress)")
}).then(result => {
console.dir(result)
callback(result);
}).catch(err => {
// ... error checks
console.log("Error occured: " + err);
callback(err);
});
}
Obviously, I'd like to write one standard method to write records to any table in the database.
Now I can fetch structure of each table and use that to find how what datatype each field should be from the key in jsonRecord and write something like this:
var insertRecordIntoTable = function (jsonRecord, tableName, callback) {
let arrKeys = jsonRecord.allKeys();
let columnNames = getCommaSeparatedColumnNames(arrKeys);
let valuePlaceholders = getValuePlaceholdersForSql(arrKeys);
sql.connect(dbConfig).then(pool => {
return pool.request()
// how do I write something like this so that dynamic number of fields and values get populated in the query inside this promise.
// I'm open to methods without promise as well.
for(let x=0; x < arrKeys.length; x++){
let key = arrKeys[x];
// .input('ID', sql.Int, 210)
.input(key, getTypeForKey(key, tableName), jsonRecord[ key ] )
}
.query("INSERT INTO " + tableName + " (" + columnNames + ") VALUES (" + valuePlaceholders + ")")
}).then(result => {
console.dir(result)
callback(result);
}).catch(err => {
// ... error checks
console.log("Error occured: " + err);
callback(err);
});
}
function getTypeForKey(key){. // looks up table schema and returns keyType }
function getCommaSeparatedColumnNames(arrKeys){ return arrKeys.join(", "); }
function getValuePlaceholdersForSql(arrKeys){ // write code to append '#' before every key and then join using comma's and return that string }
I'm sure node.js writing to SQL is a fairly common functionality and there may be better ways to achieve what I'm trying to do here. Please feel free to go a different route.
P.S. - Although I should say that I prefer mssql over Tedious package. It just seems better in functionality after going through the documentation in the last several hours.
If you want to interact with your database without creating all the queries by yourself, you can use a query builder like knex to manage the data as objects:
knex('Accounts').insert({ID: 210, Name: "John Doe", EmailAddress: "test#test.com"})
Would be similar to:
insert into `Accounts` (`EmailAddress`, `ID`, `Name`) values ('test#test.com', 210, 'John Doe')
Also I see you are checking types. If you need validation, maybe a complete ORM (I like Objection.js) would be a good choice.

Knex.js Incorrect integer value: '[object Object]' for column 'user_id' at row 1

I'm currently working on a project in express and I'm using knex.js to handle migrations and queries.
I'm still trying to grasp the concept of promises and how I can run multiple queries with knex.
I have the following code:
this.addUnit = function(unit_prefixV, unit_nameV, unit_descriptionV, profile_id) {
return knex.insert({ 'unit_prefix':unit_prefixV, 'unit_name':unit_nameV, 'unit_description':unit_descriptionV }).into('units')
.then(function(unit) {
return knex('users').where({ 'google_id':profile_id }).select('id')
.then(function(uid) {
return knex.insert({ 'unit_id':unit, 'user_id':uid }).into('users_units');
});
});
}
however I am returned with the following error:
Unhandled rejection Error: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD: Incorrect integer value: '[object Object]' for column 'user_id' at row 1
In my routes file I have the following post method:
app.post('/dashboard/unit/add', ensureAuthenticated, function(req, res) {
let postErrors = []
if (req.body.unit_name.trim() == "") {
postErrors.push('Unit name cannot be empty.')
}
if (req.body.unit_prefix.trim() == "") {
postErrors.push('Unit prefix cannot be empty.')
}
if (req.body.unit_description.trim() == "") {
postErrors.push('Unit description cannot be empty.')
}
if (postErrors.length > 0) {
res.render('addUnit', { errors: postErrors, user: req.user })
} else {
unitModel.addUnit(req.body.unit_prefix.trim(), req.body.unit_name.trim(), req.body.unit_description.trim(), req.session.passport.user.id).then(function(unit) {
res.redirect('/dashboard')
})
}
})
For reference my users table consists of:
id
google_id
my users_units table consists of:
user_id
unit_id
What am I doing wrong?
unit is an object, you'll have to access the properties (unit_id) - depending on your db you may also have to do something special to get the result inserted object (instead of just the number of rows). The error you are getting is because knex select resolves an array. You can either do first or access the first element of the array.

Getting error while inserting bulk data using bulkCreate in Sequelize

I am trying to insert a lot of data i database using Sequelize library
but it is showing some strange as I am passing an array of objects into the bulkCreate query .
I have function something like this
db.organizations
.findAll({
attributes: ['name'],
where: {
id: req.ORG_ID
}
})
.then(org => {
let i; let smsData = [];
for (i = 0; i < user.length; i++) {
let DefaultText = Utils.defaultMessage(
user[i].name,
user[i].dataValues.amount,
org[0].name
);
smsData.push({
organizationId:
user[i].dataValues.organizationEntries[0].organizationId,
mobile: user[i].mobile,
message: DefaultText,
status: 0
});
}
console.log(JSON.stringify(smsData));
db.logSms.bulkCreate([{
smsData
}]).then(() => { // Notice: There are no arguments here, as of right now you'll have to...
return db.logSms.findAll({ where: { status: 0 } });
}).then(sms => {
console.log(sms)
})
and I have also done console.log(smsData) which is showing array of objects but I am not able to understand why I am facing this error.
INSERT INTO log_sms (id,created_at,updated_at) VALUES (NULL,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
Unhandled rejection SequelizeDatabaseError: Field 'mobile' doesn't have a default value
This error is basically coming as while executing the query as u can see below the error as I have made mobile field compulsory and I am passing the array of objects which is having mobile number but still this error is coming. Please give some hint
I have got my mistake as I should remove the braces from this statement:
db.logSms.bulkCreate([{ smsData }])
it should be like this:
db.logSms.bulkCreate(smsData)

How can I implement a method, that returns collection & records count

I build rest api with sails.js.
I want implement pagination in my angularjs frontend.
To do this I should get a list of items along with the total count of items (to calculate pages count), that meet the criteria.
Unfortunately sails.js returns only data list without total records count.
I expect that the server response will look like this:
{
data: [...], // collection data
count: 193 // records count, that meet the criteria of the request.
}
How can I implement this?
you can use async.auto
async.auto(
count: functuon(callback){
Model.count(...).exec(callback);
},
data: function(callback){
Model.find(...).exec(callback);
}
},function(err,results){
console.log(results.count);
console.log(results.data);
});
I implimented a set of blueprints that will return a count in ether the header or the body
https://github.com/randallmeeker/SailsBluePrintActions/tree/master/pagination
here is an example
var query = Model.find()
.where( actionUtil.parseCriteria(req) )
.limit( actionUtil.parseLimit(req) )
.skip( actionUtil.parseSkip(req) )
.sort( actionUtil.parseSort(req) );
var metaInfo,
criteria = actionUtil.parseCriteria(req),
skip = actionUtil.parseSkip(req),
limit = actionUtil.parseLimit(req);
Model.count(criteria)
.exec(function(err, total){
if (err) return res.serverError(err);
metaInfo = {
start : skip,
end : skip + limit,
limit : limit,
total : total,
criteria: criteria
};
res.ok({info: metaInfo, items: matchingRecords});
});
You can use Model.count to count all data that meet the criteria.
Example:
// very important here to use the same `criteria` for `find` and `count`
var criteria = {foo: 'bar'};
Model.find(criteria).exec(function (err, found) {
Model.count(criteria).exec(function (error, count) {
console.log({ data: found, count: count });
});
});

Order Bookshelf.js fetch by related column value

I'm using Bookshelf.js/Knex.js, fetching a model (call it user) with a related child model (call it company).Can I order by a field on the child model - company.name?
Also, if that's possible, can I multi sort, say company.name descending then lastName ascending
Here's my current code, which only works on root model fields. qb.orderBy('company.name', 'desc') doesn't work.
users.query(function(qb) {
qb.orderBy('lastName', 'asc');
})
.fetch({withRelated: ['company']})
.then(success, error);
Try the following:
users
.fetch({withRelated: [
{
'company': function(qb) {
qb.orderBy("name");
}
}
]})
.then(success, error);
I got the idea from https://github.com/tgriesser/bookshelf/issues/361
You can do it like this without the need of a function:
users.query(function(qb) {
qb.query('orderBy', 'lastName', 'asc');
})
.fetch({withRelated: ['company']})
.then(success, error);
Found here: Sort Bookshelf.js results with .orderBy()
I think I solved it by doing this:
let postHits =
await posts
.query(qb => qb
.innerJoin('post_actor_rel', function () {
this.on('post.id', '=', 'post_actor_rel.post_id');
})
.innerJoin('actor', function () {
this.on('post_actor_rel.actor_id', '=', 'actor.id');
})
.orderByRaw('actor.name ASC')
.groupBy('id')
)
.fetchPage({
withRelated: ['roles', 'themes', 'activity_types', 'subjects', 'educational_stages', 'images', 'documents', 'actors'],
limit,
offset
},
);
I modify the query by inner joining with the desired tables and after sorting (using orderByRaw since I will need to add some more sorting that I think is not possible with orderBy) I group by the post's id to get rid of the duplicate rows. The only problem is that it's not defined which actor name (of several possible) is used for the sorting.

Resources