JS beginner trying to get a PostgreSQL DB talking to express.js through bookshelf.js.
github: https://github.com/duskyshelf/bookers-academy/blob/master/booker.js
var knex = require('knex')({
client: 'pg',
connection: "postgres://localhost/bookers"
});
var bookshelf = require('bookshelf')(knex);
var User = bookshelf.Model.extend({
tableName: 'users'
});
var bob = new User({id: 2});
bob.save()
bookshelf.js seems unable to add any content to the db.
Current error message is: "Unhandled rejection CustomError: No Rows Updated'
When you create your model providing your own id, like in
var bob = new User({id: 2});
Bookshelf assumes it is an update operation, not an insertion. It sets the internal isNew attribute to false, and when save() is invoked, instead of INSERT INTO user(id, ...) VALUES (2, ...);, it executes UPDATE user ... WHERE id = 2;.
If there is no user with id = 2 the update will almost silently DO NOTHING.
To force an insert you must change the save() to:
bob.save(null, {method: 'insert'});
Bookshelf save() documentation describes this behavior.
Did you create a User table using knex? One potential problem I can think of is that you do not have any logic that actually creates the table for your Postgres DB. Here is some sample code that will create a table in your database if it doesn't yet exist.
bookshelf.knex.schema.hasTable('User').then(function(exists) {
if(!exists) {
bookshelf.knex.schema.createTable('User'), function(user) {
user.increments('id').primary();
user.timestamps();
}).then(function(table){
console.log('Created Table:', table);
});
}
});
new User({id: 2}).
save().
then((model) => {
res.json({ success: true });
});
No no! new User returns a PROMISE! You can't use it like that.
Try
new User().save()
Related
I am new to Parse Server.
I am having an existing collection "users" in "employee" db in Mongodb.
I need to get the users data using Parse Server.
Below is the code:
var query = new Parse.Query(users);
query.find().then((data) => {
return data;
}).catch((error) => {
return error;
});
But I am getting the error "users" is not defined.
Need some valuable help.
if your Class really is called users (which is different to the built-in Parse Server Class called User), then use :
var query = new Parse.Query('users'); //note the quotation around 'users'
If you are in fact trying to query the built-in User class, use :
var query = new Parse.Query(Parse.User);
or
var query = new Parse.Query('_User');
This is my Schema:
var userScheme = mongoose.Schema({
aField:String,
info: {
type:{
local: {
email:String
}
},
select:false
}
});
When I try to create a new user this works fine:
var newUser = new User()
newUser.aField="Something"
newUser.save()
But when I try to access the field that has select:false, I can't access the data. so this doesn't work:
var newUser = new User()
newUser.aField="something"
newUser.info.local.email="email#domain.com"
newUser.save()
The error I get is:
TypeError: Cannot read property 'local' of undefined
My guess is that the new Model is returned without the info field becuase it is set to select:false.
How can I make the new Model() return all the fields including those set to 'select:false'?
Thanks!
Turns out the select:false had nothing to do with it.
The culprit was the fact that info has no values by default and there for was not included in the model at all.
The solution was to create a new schema just for info, and to include it in the user schema like this:
var userScheme = mongoose.Schema({
aField:String,
info: {
type:infoSchema,
default:infoSchema, //Without this, the new document will still not include an 'info' document,
select:false
}
});
Hope this helps anyone. This was just 3 hours of my life.
I am using postgresql, knex, and bookshelf to make queries to update my users table. I would like to find all users who didn't sign in during a specific time and then update their numAbsences and numTardies field.
However it appears that when running a raw sql query using bookshelf.knex the result that I get for users is an array of objects rather than an array of bookshelf objects of objects because I can't save the objects directly to the database when I try to use .save(). I get the exception user.save is not a function.
Does anyone know how I can update the values in the database for the users? I've seen the update function but I need to also return the users in absentUsers so I select them currently.
// field indicates whether the student was late or absent
var absentUsers = function(field){
// returns all users who did not sign in during a specific time
if (ongoingClasses){
return bookshelf.knex('users')
.join('signed_in', 'signed_in.studentId', '=', 'users.id')
.where('signed_in.signedIn', false)
.select()
.then(function(users){
markAbsent(users, field);
return users;
});
}
}
var markAbsent = function(users, field){
users.forEach(function(user){
user[field]++;
user.save();
})
}
I've solved my problem by using another sql query in knex. It seemed there was no way to use a sql query and then use standard bookshelf knex methods since the objects returned were not bookshelf wrapper objects.
var absentUsers = function(field){
// returns all users who did not sign in during a specific time
if (ongoingClasses){
return bookshelf.knex('users')
.join('signed_in', 'signed_in.studentId', '=', 'users.id')
.where('signed_in.signedIn', false)
.select()
.then(function(users){
markAbsent(users, field);
});
}
}
var markAbsent = function(users, field){
users.forEach(function(user){
var updatedUser = {};
updatedUser[field] = user[field]+1;
bookshelf.knex('users')
.where('users.id', user.id)
.update(updatedUser).then(function(){
});
});
}
With your code bookshelf.knex('users') you leave the "Bookshelf world" and are in "raw knex world". Knex alone doesn't know about your Bookshelf wrapper objects.
You may use Bookshelf query method to get the best of both worlds.
Assuming your model class is User, your example would look approximately like
User.query(function(qb) {
qb.join('signed_in', 'signed_in.studentId', 'users.id')
.where('signed_in.signedIn', false);
})
.fetchAll()
.then(function(bookshelfUserObjects) {
/*mark absent*/
return bookshelfUserObjects.invokeThen('save'); // <1>
});
<1> invokeThen: Call model method on each instance in collection
I am trying:
if (process.NODE_ENV === 'test') {
foreignKeyChecks = 0;
forceSync = true;
} else {
foreignKeyChecks = 1;
forceSync = false;
}
global.db.sequelize.query("SET FOREIGN_KEY_CHECKS = " + foreignKeyChecks).then(function() {
return global.db.sequelize.sync({
force: forceSync
});
}).then(function() {
return global.db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1');
}).then(function() {
var server;
console.log('Initialzed database on:');
console.log(config.db);
return server = app.listen(port, function() {
return console.log("Server listening at http://" + (server.address().address) + ":" + (server.address().port));
});
})["catch"](function(err) {
return console.log('err', err);
});
module.exports = app;
But I get: SequelizeDatabaseError: unrecognized configuration parameter "foreign_key_checks"
I assume I can't have that keyword in postgres? But is there an equivalent way to drop all tables and recreate?
This is an updated answer, targeted at the googlers who wound up here like me.
Sequelize offers a drop function:
drop(options) => promise
Drop all tables defined through this sequelize instance. This is done by calling Model.drop on each model. Sequelize docs
Example
var sequelize = new Sequelize(config.database, config.username, config.password, config);
var someModel = sequelize.define('somemodel', {
name: DataTypes.STRING
});
sequelize
.sync() // create the database table for our model(s)
.then(function(){
// do some work
})
.then(function(){
return sequelize.drop() // drop all tables in the db
});
For wiping out data and create all again from scratch (like in tests):
sequelize.sync({force: true});
I don't know anything about that JavaScript library, but Postgres provides a single command to drop everything that is owned by a user:
drop owned by <our_user_name cascade
This will only work if everything is owned by the same user and that user doesn't have some tables (or views, sequences, ...) that you do not want to drop.
More details in the manual:
http://www.postgresql.org/docs/current/static/sql-drop-owned.html
For anyone looking for a solution with sequelize-cli checkout this link Sequelize CLI:
You can just run:
sequelize_cli db:drop
sequelize_cli db:create
To create or drop your db using the cli tool. This way you will have a empty db.
I want to retrieve the last inserted _id, using mongoose as MongoDB wrapper for node.js. I've found the following tutorial, but I can't change any node modules because the app runs on a public server:
Getting "Last Inserted ID" (hint - you have to hack Mongoose)
Any other ideas? This what I want to do:
Insert new user
Get user's _id value
Set a new session based on user's id
Redirect to /
Thanks!
I'm using mongoose version 1.2.0 and as soon as I created a new instance of a mongoose model, the _id is already set.
coffee> u = new User()
[object Object]
coffee> u._id
4dd68fc449aaedd177000001
I also verified that after I call u.save() the _id remains the same. I verified via MongoHub that this is indeed the real ID saved into MongoDB.
If you explicitly declare
_id: Schema.ObjectId
for your model, then the ObjectId will not be available after new or save.
This is probably a bug.
If you're looking to get the last inserted _id of a sub object, then create the object, and add it to the item. Here's an example in NowJS using MongoDB and Mongoose (to add some schema sugar) which then converts the result to JSON to send back to the client:
var nowRoomID = this.now.room;
var Conversation = mongoose.model('Conversation');
Conversation.findById(convID, function(error, conversation) {
var Blip = mongoose.model('Blip');
var createdBlip = new Blip();
createdBlip.author= nowUserName;
createdBlip.authorid = parsed.authorid;
createdBlip.body = revisedText;
createdBlip.created_at = new Date();
createdBlip.modified_at = new Date();
conversation.blips.push(createdBlip);
parsed._id = createdBlip._id; //NOTE: ID ACCESSED HERE
message = JSON.stringify(parsed);
conversation.save(function (err) {
if (!err) {
console.log('Success - saved a blip onto a conversation!');
nowjs.getGroup(nowRoomID).now.receiveMessage(nowUserName, message);
}
});
With MongoDB, if you don't explicitly set a document's _id value then the client driver will automatically set it to an ObjectId value. This is different from databases that might generate IDs on the server and need another query to retrieve it, like with SQL Server's scope_identity() or MySQL's last_insert_id().
This allows you to insert data asynchronously because don't need to wait for the server to return an _id value before you continue.
So, as shown is Peter's answer, the _id is available before the document is saved to the database.
I just get the id from the document passed to the callback, since save returns the saved document.
Check below url
http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
you will find following code in given url
var document = {name:"David", title:"About MongoDB"};
collection.insert(document, {w: 1}, function(err, records){
console.log("Record added as "+records[0]._id);
});