Sequelize - Custom Create Method - node.js

Is it possible to create a custom create method in Sequelize. I would like it so that I could pass in a URL to download a thumbnail photo from, and then a method would be called with that data to download the photo, upload it to S3, and save that S3 URL as the thumbnailPhotoURL.
Here is an example of the syntax I'm trying to do:
var Sequelize = require('sequelize');
var sequelize = new Sequelize('database', 'username', 'password');
var User = sequelize.define('user', {
username: Sequelize.STRING,
birthday: Sequelize.DATE,
thumbnailPhotoURL: Sequelize.STRING
});
sequelize.sync().then(function() {
return User.create({
username: 'janedoe',
birthday: new Date(1980, 6, 20),
// this will be used to download and upload the thumbnailPhoto to S3
urlToDownloadThumbnailPhotoFrom: 'http://example.com/test.png'
});
}).then(function(jane) {
console.log(jane.get({
plain: true
}));
});
Notice how I'm calling User.create with a urlToDownloadThumbnailPhotoFrom parameter, rather than a thumbnailPhotoURL parameter

You can use before create hook no need to define a custom create function
var Sequelize = require('sequelize');
var sequelize = new Sequelize('database', 'username', 'password');
var User = sequelize.define('user', {
username: Sequelize.STRING,
birthday: Sequelize.DATE,
thumbnailPhotoURL: Sequelize.STRING
});
User.beforeCreate(function(model, options, cb) {
var urlToDownloadThumbnailPhotoFrom = model.urlToDownloadThumbnailPhotoFrom;
//.....Here you write the logic to get s3 url using urlToDownloadThumbnailPhotoFrom and then assign it to model and call the call back it will automatically get saved
model.thumbnailPhotoURL = thumbnailPhotoURL;
cb();
});

Related

Is there a problem with not following the structure of the created model and saving data with different information?

I'm a newbie and I'm doing a backend with nodeJS + Express + mongoDB.
So I have this model:
const user = new Schema({
email: String,
password: String,
lastName: String,
firstName: String
})
module.exports = model('User', user);
Then when a user signs Up I save the data :
const createUser = new User({
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8),
id: req.body.id,
lastName: req.body.lastName,
firstName: req.body.firstName,
photoUrl: req.body.photoUrl,
});
createUser.save((err, user) => {
if (err) {
res.status(500).send({message: err});
}else{
res.send({message: 'Complete'});
}
}
So I don't know If when I add new data "photoUrl" that doesn't exist in my main model it could affect the app or with other CRUD functions
Mongoose by default have strict: true flag on schema which basically means that values passed to model constructor that were not specified in the schema do not get saved to the db. So basically all the extra fields passed will be just skipped.
You will have to expicitly disable the strict in order to add the field that is not specified in the DB.
Following example taken from mongoose documentation
// set to false..
const thingSchema = new Schema({..}, { strict: false });
const thing = new Thing({ iAmNotInTheSchema: true });
thing.save(); // iAmNotInTheSchema is now saved to the db!

Sequelize could not create a new table

I'm currently learning sequelize and its define method is used to create new database table, but it is not working...there is no error...do you know whats going on?
var express = require('express');
var Sequelize = require('sequelize');
var sequelize = require('../db/sequelize_conf.js');
var router = express.Router();
var User = sequelize.define('user',
{
name: Sequelize.STRING,
password: Sequelize.STRING,
mail: Sequelize.STRING
},
{
freezeTableName: true,
timestamps: false
});
User.create({
name: 'XiaoMing',
password: '1234567890',
mail: 'xiaoming#qq.com'
}).then(function(result){
console.log('inserted XiaoMing ok');
}).catch(function(err){
console.log('inserted XiaoMing error');
console.log(err.message);
});
module.exports=router;
It says the user table doesnt exist....
Okay ,
First check in the database if user table is there or not , coz the below code won't create a new table , it will just create a new entry in to user table
User.create({
name: 'XiaoMing',
password: '1234567890',
mail: 'xiaoming#qq.com'
})
If you want to create a table then you can use ,
// This will create only all the tables defines via sequelize
sequelize.sync().then(() =>
// put your user create code inside this
);
// OR
// This will create only user table
User.sync().then(() => {
// put your user create code inside this
});
I hope this will clear all your doubts

MongoError: E11000 duplicate key error

i'm making a simple blog app using nodejs + express, i can add first post without a problem but when i try to add second post i got his error { MongoError: E11000 duplicate key error collection: restful_blog_app_v2.blogs index: username_1 dup key: { : null }
this is my schema
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var BlogSchema = new mongoose.Schema({
title: String,
image: String,
body: String,
created: {
type: Date,
default: Date.now
},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
BlogSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("Blog", BlogSchema);
this is the user schema
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String,
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
this is the create new post route
app.post("/blogs", isLoggedIn, function (req, res) {
req.body.blog.body = req.sanitize(req.body.blog.body);
var title = req.body.blog.title;
var image = req.body.blog.image
var body = req.body.blog.body;
var created = req.body.blog.created;
var author = {
id: req.user._id,
username: req.user.username
}
var newPost = {
title: title,
image: image,
body: body,
created: created,
author: author
}
Blog.create(newPost, function (err, newBlog) {
if (err) {
console.log(err);
res.render("new");
} else {
console.log(newBlog);
res.redirect("/blogs");
}
});
});
I've tried to dropped the entire database using db.dropDatabase() from the mongo console but the problem still persist, not sure what to do now
This is caused by passport-local-mongoose, which, according to its fine manual, makes username a unique field by default.
You have added this plugin to BlogSchema, which seems like you initially had the user data in that schema but moved it to a separate schema (UserSchema) and forgot to remove it from the former.
Start by not using it for BlogSchema, and you also need to drop the unique index on username on the blogs collection.
Can you try deleting your Schema and again send the value? I was getting the same issues. I solved with the above idea.

Node js and Code First

I've worked on Entity Framework with Code First approach. Now I am learning Node.js I wonder is there a way to make the same code first approach using Node.js and some libraly? I am thinking of using MySql as database.
You can look into Sequelize. Example of usage from the home page (I added comments to relate to Code First):
var Sequelize = require('sequelize');
// define your "context"
var sequelize = new Sequelize('database', 'username', 'password');
// define your "entities"
var User = sequelize.define('user', {
username: Sequelize.STRING,
birthday: Sequelize.DATE
});
// use them
sequelize.sync().then(function() {
return User.create({
username: 'janedoe',
birthday: new Date(1980, 6, 20)
});
}).then(function(jane) {
console.log(jane.get({
plain: true
}));
});

Save mongoose document again after deleting it

I try to unit test my restify node.js-app using mocha and without mocking out the mongodb database. As some tests will alter the database, I'd like to reset its contents before each test.
In my tests I also need to access the mongoose documents I am creating. Thus I have to define them outside of the beforeEach hook (see the user document below).
However, it seems like it's not possible to save a document a second time after emptying the database.
Below is a minimal example I've come up with. The second test will fail in that case, because user won't get saved a second time. If I delete the first test, beforeEach only gets called once and everything works nicely.
Also if I define user inside the beforeEach hook, it works as well.
So my actual question: Is it possible to work around this issue and save a document a second time after deleting it? Or do you have any other idea on how I can reset the database inside the beforeEach hook? What's the proper way to have the same database setup before each test case?
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var should = require('should')
var flow = require('async')
var UserSchema = new Schema({
username: {type: String, required: true, unique: true},
password: {type: String, required: true},
name: {type: String, default: ''}
})
mongoose.model('User', UserSchema)
var User = mongoose.model('User')
describe('test mocha', function() {
var user = new User({
username: 'max',
password: 'asdf'
})
before(function(done) {
var options = {server: {socketOptions: {keepAlive: 1}}}
mongoose.connect('mongodb://localhost/unittest', options, done)
})
beforeEach(function(done) {
flow.series([
function(callback) {
User.collection.remove(callback)
}, function(callback) {
user.save(callback)
}
], function(err, res) {
done()
})
})
it('should pass', function(done) {
true.should.equal(true)
// also access some elements of user here
done()
})
it('should have a user', function(done) {
User.find().exec(function(err, res) {
res.should.not.be.empty
})
done()
})
after(function(done) {
mongoose.disconnect()
done()
})
})
I faced same problem,I generated a copy of the document to save. When need to save the document after deleting it I saved the copy, and it worked. Like
var user = new User({
username: 'max',
password: 'asdf'
});
var userCopy = new User({
username: 'max',
password: 'asdf'
});
And in test cases.
user.remove(callback)
}, function(callback) {
userCopy.save(callback){
// should.not.exist(err)
}
}
It might not be good solution ,but it worked for me.

Resources