Getting error while inserting bulk data using bulkCreate in Sequelize - node.js

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)

Related

I get a "($) prefixed field '$numberDecimal' in 'price.$numberDecimal' is not valid for storage." error when trying to update a field on my back-end

lately I've been trying to update a price field in my mongodb database but I'm facing an annoying issue.
The collection I'm trying to modify is listingsandReviews, within the database sample_airbnb.
The field in question is made as such price {$numberDecimal: priceVar}.
On my back end (using Express.js DAO architecture), my update query looks as such:
// console.log(roomContent.amenities)
let price = roomContent.price.$numberDecimal
try {
const roomIdResponse = await rooms.updateOne(
{ _id: roomId },
{ $set: {
name: roomContent.name,
address: {street: roomContent.address.street},
price: {'$numberDecimal': price},
property_type: roomContent.property_type,
bedrooms: roomContent.bedrooms,
beds: roomContent.beds,
minimum_nights: roomContent.minimum_nights,
maximum_nights: roomContent.maximum_nights,
amenities: roomContent.amenities,
description: roomContent.description
}
},
{ upsert: true }
);
return roomIdResponse;
}
catch (e) {
console.error(`Unable to update room: ${e}`);
return { error: e };
}
}
the shell gives me back that error Unable to update room: MongoServerError: The dollar ($) prefixed field '$numberDecimal' in 'price.$numberDecimal' is not valid for storage.
I've been looking at every resource possible, some saying I should try NumberDecimal(), others decimal128, but nothing works so far.
You could say I could fix the issue on the front-end, but that wouldn't make the database structure consistent, which I want to avoid.

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.

Updating Mongo DB entries by params

The goal of this program is to add a property called 'userResponse' to the problem objects that reflects the input from the user. The problem object in Mongo DB is held in an array of objects, called 'problems', that is held in an object called 'session':
{
"_id" : ObjectId("59df5ee7adb378237377dbb4"),
"updatedAt" : ISODate("2017-10-12T12:24:07.269Z"),
"createdAt" : ISODate("2017-10-12T12:24:07.269Z"),
"userId" : "59df5edbadb378237377dbb3",
"problems" : [
{
"correctResponse" : 23,
"problem" : "20 + 3",
"secondTerm" : 3,
"firstTerm" : 20
} ]
}
Here is the logic for the endpoint that I have been using:
router.patch( '/session/:sessionId/:index', passport.authenticate( 'jwt', { session: false } ), ( req, res ) => {
Session.findOne({_id: req.params.sessionId})
.then( (item)=>{
item.problems[req.params.index].userResponse = req.body.userResponse;
Session.update({_id: req.params.sessionId}, item).then( (updated)=>{
res.json(updated.problems[req.params.index]);
});
})
})
I looked at some other examples ( one two ) but they do not seem relavant since this is a patch to single elements of the array as identified by the params.
This approach works, in that it successfully updates the database with the new properties on the objects, but during the execution the server logs this error:
(node:10955) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property '0' of undefined
My understanding is that this means the object can not be found in the database at some point, but since the database does include the new properties it must be resolved later. Is that corrrect?
Additionally it seems brittle to have two chained promises with no catch statements...
Can anyone offer suggestions on how to improve this process? This logic does successfully update the database, with errors. Is there a better way?
Thank you for your time.
Well i can see multiple issues in the code that can cause your problem
1- From the structure of your database session document _id is of type ObjectId and when you try to find, you are finding by just the id which is probably string you will need to use ObjectId(req.params.sessionId)
2- from the error, i can tell that the value of item does not contain an array of problems ... so items.problems is undefined so undefined[0] is an error.
3- You don't need to find session document item twice to update the array, i updated the code to update the userResponse value in array by using a single update operation.
4- for a better error handling and code maintainability you need to handle promise rejection so you need to handle catch as well as you are doing with then
So from the above comments i can update your code to be
var mongoose = require('mongoose');
router.patch( '/session/:sessionId/:index', passport.authenticate( 'jwt', { session: false } ), ( req, res ) => {
var index = req.params.index;
Session.update({_id: mongoose.Types.ObjectId(req.params.sessionId) }, {$set : {"problems." + index + ".userResponse" : req.body.userResponse } )
.then( (updated)=>{
console.log(updated);
res.json(updated.problems[req.params.index]);
})
.catch((err) => {
console.log(err.message);
res.json({status: "error" , message:err.message});
});
})

Mongodb duplicate errorr

db.collection("resource").update({name: name}, {
name: name,
type: type
}, {
upsert: true
}
I differentiate documents by their names. I do not add document if it exists with the same. But I want to warn user by saying "It already exists, operation failed" How can I achieve it?
It sounds like you want to insert documents, not update or insert documents.
1: Add unique index on resource.name ahead of time.
db.resouces.createIndex({ name: 1 }, { unique: true })
Important: do this once, not on every request.
See mongodb create index docs.
2: Use insert instead of update + upsert.
It sounds like you want to actually insert a document, and get an error if there is a duplicate key.
db.resources.insert({ name: "AJ" }) // ok
db.resources.insert({ name: "AJ" }) // error!
You will get a duplicate key error on the second insert. Error code 11000.
See mongodb docs on insert.
3: Use promise-try-catch in javascript.
The code to do error checking looks like:
var db = require("mongojs")(DATABASE_URL, [ "resources" ])
var duplicateKey = function (err) {
return err.code == "11000"
}
db.resources.insert({ name: name })
.then(function () {
// success!
})
.catch(duplicateKey, function () {
// sorry! name is taken
})

:Sequelize how set returned data order

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'
})

Resources