I'm using Sequelize and I'm trying to get the last inserted ID in raw query.
My query is
.query(Sequelize.Utils.format(["insert into MyTable (field1, field2) values (?,?)", val1, val2])
The query is done perfectly, but the result on success event is null.
Can someone help?
Thanks.
After some researches and zillions attempts, I understood how callee object work in sequelizeJs.
please, correct me if my answer is wrong.
the callee object needs this structure
{__factory:{autoIncrementField: 'parameterName'}, parameterName: '' }
in this case "parameterName" is the field that will store the new ID, sequelize looks for __factory.autoIncrementField to set value of last inserted id into property with its value (value of __factory.autoIncrementField).
so, my call to querys method would be
.query(sequelize.Utils.format(tempInsert), {__factory:{autoIncrementField: 'parameterName'}, parameterName: '' }, {raw: true})
this will result in object like that
{ __factory: { autoIncrementField: 'parameterName' }, parameterName: newInserted_ID }
thanks for all, and I hope this can help someone.
You have to add autoIncrement property in model definition.
const Article = sequelize.define('articles', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
}, {},
{
createdAt: false,
updatedAt: false
});
Then, you can access last inserted id with property in model definition.
Article.create(article)
.then(result => console.log(result.id));
Yes your answer is working. Another way would be
var Sequelize = require("sequelize")
var sequelize = new Sequelize('test', 'root', 'root', {dialect: 'mysql'})
var Page = sequelize.define( 'page', {
type : {type: Sequelize.STRING(20)},
order : {type: Sequelize.INTEGER, defaultValue: 1}
},{
timestamps: false,
underscored: true
})
Page.__factory = {autoIncrementField: 'id'}
Page.id = ''
sequelize.query('INSERT INTO pages SET `type` = ?, `order` = ?, `topic_version_id` = ?', Page, {raw: false}, ['TEXT', 1, 1] ).success(function(page) {
console.log(page)
Page.find(page.id)
.success(function(result){
console.log(result)
})
})
const addAuthUser = await authModel.create(
{
username: username,
password: hashedPassword
});
if (!addAuthUser) {
return next(new HttpError('SignUp Failed!', 401));
}
// this last inser id
console.log(addAuthUser.id)
Related
I am using mongoose along with nodejs to insert data. I am using MVC and in my controller I have this code:
module.exports.create_tracsaction = function (req, res) {
Company.findOne({ username: req.body.req_from }, function (err, user) {
if (user.vaccine.extra < req.body.req_vac) {
return res.redirect('/vaccine');
}
else {
var data = {
req_from: req.body.req_from,
req_to: req.body.req_to,
amt_req: req.body.req_vac,
transaction_status: "Awaiting confirmation",
vaccine: user.vaccine.name,
transaction_value: user.vaccine.price * req.body.req_vac
}
Transaction.create(data);
return res.redirect('/vaccine');
}
})
console.log(req.body);
};
This is my schema
const transactionSchema = new mongoose.Schema({
req_from: {
type: String,
required: true
},
req_to: {
type: String,
required: true
},
amt_req: {
type: Number,
required:true
},
transaction_status: {
type: String,
default: "Awaiting confirmation"
},
vaccine: String,
transaction_value: Number
}, {
timestamps: true
});
Even though non of the fields have property unique:'true', I am getting this error:
MongoError: E11000 duplicate key error collection: innovate_dev.transactions index: username_1 dup key: { username: null }
How to remove this error? The first time I sent data from views there was no error but from thereafter it's giving this error every time.
Let me know if you need anything else. Thanks in advance :D
It looks like a unique index got created at some point on the username field of transactions. That according your schema, it no longer exists. Thus every time you make an entry null is being indexed and throwing an error.
If you are using Compass or another GUI you can go in and delete it.
Otherwise to remove with MongoShell:
use innovate_dev
It will switch to your db
db.transactions.dropIndex('username_1')
I have the following schema:
const userSchema = new mongoose.Schema({
email: [{
type: String,
trim: true,
}]
})
When saving a new user,
const user = new User({
email: ["example#example.com", ""]
//or email: ["example#example.com", null]
})
try{
await user.save()
} catch (e) {
console.log(e)
}
This will save both those values (including empty string and null respectively).
Is there a way to save only the proper email value while discarding the empty or null value.
Instead of this:
"email" : [
"example#example.com",
""
],
store only the proper email:
"email" : [
"example#example.com",
],
Currently for other schema fields I am using set. For example, in the user schema above
url: {
type: String,
set: deleteEmpty
}
const deleteEmpty = (v) => {
if(!v) {
return undefined
}
return v
}
This will of course not save the url field at all if the value is empty or null.
Using this method on the email field above however will generate a null value.
Is there a way to store only the proper email value (i.e. "example#example.com" in this case while ignoring the null or empty value.)?
👨🏫 I think you can make it something like this code below 👇 with your userSchema:
userSchema.pre('save', function(next) {
this.email = this.email.filter(email => email);
next();
})
The code above ☝️ will igrone all empty or null value in an array. You can try it.
Or the Second Options, you can add required on your email field in your userSchema. It's well looks like this code below: 👇
const userSchema = new mongoose.Schema({
email: [{
type: String,
trim: true,
required: true // add some required
}],
});
💡 The code above ☝️, will give you an error if you passing an empty string on your array.
I hope it's can help you 🙏.
You can do the following to achieve what you want.
var arr = ['example#example.com', '']; // variable to keep the an array containing values
var i;
for (i = 0; i < arr.length; i++) {
if (arr[i] == null || arr[i] == '') {
arr.slice(i); // remove null or '' value
}
}
console.log('normalized array: ', arr);
// schema code
const user = new User({
email: arr
})
try{
await user.save()
} catch (e) {
console.log(e)
}
Good luck, I hope I answered your question.
If anyone has one or more fields that takes array value and wants to check for each field, I recommend using a middleware on the pre save hook.
supplierSchema.pre('save', normalizeArray)
const normalizeArrray = function(next) {
//take the list of object feilds and for each field check if it is array
Object.keys(this.toObject()).forEach((field) => {
if(Array.isArray(this[field])) {
//removes null or empty values
this[field] = this[field].filter(field => field)
}
})
next()
}
This just builds on the answer already approved above.
Simply set the default value of the field you wish to ignore, if empty, to undefined. Also, set required to false.
Use the code below:
const userSchema = new mongoose.Schema({
email: [{
type: String,
trim: true,
required: false,
default: undefined
}]
})
Most answers I have found are from old posts, I saw Partial Index but no good example on how to use it, also I initiate my index when I start up mongoose again cant find examples on how to set it up to work with Partial Index.
// db is read from a config file
mongoose.connect(db.uri, {autoIndex: db.autoIndex, useNewUrlParser: true});
The problem if I want a property like email to be optional also unique and indexed, but when I update its set to null or empty space even if I force it to be undefined and that causes a duplicate error.
This the solution I have came up with it works but is their any better way, here is my simplified model in all its glory
let UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
trim: true,
index: {unique: true, sparse: true}
}
});
// this run when creating a new user
UserSchema.pre('save', function (next) {
if (this.email === null || this.email === '') {
this.email = undefined;
}
next();
});
// this runs when updating a user
UserSchema.pre('update', function () {
const update = this.getUpdate();
let fix = {};
if (update.email === null || update.email === '') {
delete this._update.email;
fix.email = true;
}
this.update({}, {$unset: fix});
});
// Also what about findOneAndUpdate method will I need a pre method too
After digging deeper I finally solved it, using Partial indexes and setting a function for cases of empty strings which will throw duplicate error, so nulls will work just fine for undefined values and will be considered unique
let UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
trim: true,
index: {
unique: true,
partialFilterExpression: {email: {$type: 'string'}},
},
set: v => (v === '' ? null : v)
}
});
Why the query below executes SELECT id, email, name FROM users AS users WHERE users.email = 'admin#admin.com'; rather than SELECT * from users WHERE email = admin#admin.com ?
http://docs.sequelizejs.com/en/latest/docs/querying/#where
Documentation states that it'll run a SELECT * query when I do findAll(), but it does something different in my example. What's missing here?
Here's my users model.
var user = sequelize.define('users', {
id : {
type : Sequelize.INTEGER,
primaryKey : true,
autoIncrement : true
},
email : {
type : Sequelize.STRING
},
name : {
type : Sequelize.STRING
}
},
{
tableName: 'users',
freezeTableName: true
});
And this is my query. It seems that it only selects defined columns, but I don't want this.
var email = "admin#admin.com";
user.findAll({where: {email: email}}).then(function (user) {
res.send(user);
}).error(function (err) {
console.log("Error:" + err);
});
This is expected behavior of sequelize selecting only the columns which you have defined. If you want to select all of the columns using sequelize you must define them in your model.
I have created a table in postgresql 9
create table stillbirth(id serial primary key, state varchar(100), count int not null, year int not null);
trying to write a sample on node.js with sequelize 1.4.1 version.
mapped the above table as
var StillBirth = sequelize.define('stillbirth',
{ id: {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
state: Sequelize.STRING,
year: Sequelize.INTEGER,
count: Sequelize.INTEGER
}, {timestamps: false, freezeTableName: true});
now when i try to create a new instance of Stillbirth and save it, i get errors.
/** new instance create code **/
StillBirth
.build({state: objs[j].state, year: objs[j].year, count: objs[j].count})
.save()
.error(function(row){
console.log('could not save the row ' + JSON.stringify(row));
})
.success(function(row){
console.log('successfully saved ' + JSON.stringify(row));
})
error i get
*Executing: INSERT INTO "stillbirth" ("state","year","count","id") VALUES ('Andhra Pradesh',2004,11,NULL) RETURNING ;
could not save the row {"length":110,"name":"error","severity":"ERROR","code":"23502","file":"execMain.c","line":"1359","routine":"ExecConstraints"}
If you look at the sql that its generating, it puts null for the primary key which should ideally be generated by the db.
Can someone help me as to what am i missing here ?
You have to instantiate Sequelize with a special flag called omitNull:
var sequelize = new Sequelize('db', 'user', 'pw', {
omitNull: true
})
This will disable inserting undefined values as NULL. http://sequelizejs.com/#usage-options
You might need to update to v1.5.x or 1.6.0-betaX
To expand on the answer from sdepold, as he recommended, you can omitNull to prevent sequelize from adding null values to the generated SQL. In general, this is good, and it also allows you to perform partial updates.
var sequelize = new Sequelize('db', 'user', 'pw', {
omitNull: true
})
There is one caveat, though. How do you set a column to null if that's legitimately what you want to do?? The answer is that you can pass omitNull as part of your save.
user.address = null;
user.save({omitNull: false});
OR
user.update({address: null}, {omitNull: false});
It is also possible to define which attributes can be set via the create method. Using that would for example allow you to restrict the User model to set only a username and an address but not an admin flag:
User.create({ username: 'barfooz', isAdmin: true }, { fields: [ 'username' ] }).then(user => {
// let's assume the default of isAdmin is false:
console.log(user.get({
plain: true
})) // => { username: 'barfooz', isAdmin: false }
})
There is a workaround this without using omitNull.
Just do this:
StillBirth
.build({state: objs[j].state, year: objs[j].year, count: objs[j].count})
.save(['state','year','count'])
.error(function(row){
console.log('could not save the row ' + JSON.stringify(row));
})
.success(function(row){
console.log('successfully saved ' + JSON.stringify(row));
})
By sending an array of properties as parameter for save method you force sequelize to insert only the properties of that array omiting the id, leaving to the DB to auto create the id for you. =)