I have a form which I have separated its content into two mongodb schema
I would like to read variables which are inside node.js/express.js directly in mongoose schema hooks
either through the pre or post hooks of the schema. these are my files
express.js
var firstName = req.body.first_name;
var lastName = req.body.last_name;
var fullName = firstName+' '+lastName;
var employmentDate = req.body.employment_date;
var responsibility = req.body.responsibility;
userschema.full_name = fullName;
userschema.first_name = firstName;
userschema.last_name = lastName;
userschema.save(function (err, result){
});
/******************express UPDATE START**********/
user = new userschema(req.body)
employment = new employmentObject(req.body)
employment.employment_date= employmentDate;
employment.responsibility= responsibility;
/******************express UPDATE ENDS**********/
Schema.js
var userSchema = mongoose.Schema({
full_name : String,
other_name : String,
last_name : String,
email : String
});
userSchema.pre('save', function (){
//obtain values from form field
var field1 = employmentDate;
var field2 = responsibility;
const employmentObject = this.model('employment-detail');
/******************schema UPDATE START**********/
var emp_Date = employmentObject.employment_date;
var duties = employmentObject.responsibility;
/******************schema UPDATE ENDS**********/
employmentObjectins = new employmentObject({
'employment_date': formField1,
'responsibility' :formField2
});
employmentObjectins.save(function (err){
if(err){
console.log(err+' error saving object');
}
else{
console.log('no error in saving object');
}
});
});
This is the just the summarized content, it is longer than this. But this is the main concept.
The major areas is in getting express.js content into the model's schema
UPDATE
employmentDate and responsibility is not in the userSchema but it is in the employmentSchema
How can I get the fields which are not in userSchema (the main schema) but are in the employmentSchema
( the second schema)
SECOND UPDATE
With the modification above it is producing error
ParallelSaveError: Can't save() the same doc multiple times in parallel. Document:
What am i doing wrong
THIRD UPDATE
When I made modification based on what you said, I discovered that when I have two models
declared in express.js with their model fields/variables and I call the second model in the
pre hook of the first model it was giving me this error
Can\'t save() the same doc multiple times in parallel.
After making modification to the code. These are the files which exist
Express.js
var firstName = req.body.first_name;
var lastName = req.body.last_name;
var fullName = firstName+' '+lastName;
var employmentDate = req.body.employment_date;
var responsibility = req.body.responsibility;
userschema.full_name = fullName;
userschema.first_name = firstName;
userschema.last_name = lastName;
userschema.save(function (err, result){
});
employment.employment_date= employmentDate; <---
employment.responsibility= responsibility; <---
//I believe that I would need to declared this in order to use it in the schema
user = new userschema(req.body)
employment = new employmentObject(req.body)
userschema.js
var userSchema = mongoose.Schema({
full_name : String,
other_name : String,
last_name : String,
email : String
});
userSchema.pre('save', function (){
//obtain values from form field
var field1 = employmentDate;
var field2 = responsibility;
const employmentObject = this.model('employment-detail');
var emp_Date = employmentObject.employment_date;<-- I am calling what I declared earlier
var duties = employmentObject.responsibility;<-- I am calling what I declared earlier in express
**//when I declared above two lines it brings up the error **
**//Can't save() the same doc multiple times in parallel.**
employmentObjectins = new employmentObject({
'employment_date': emp_Date,
'responsibility' :duties
});
employmentObjectins.save(function (err){
if(err){
console.log(err+' error saving object');
}
else{
console.log('no error in saving object');
}
});
});
This is what i do in my projects
let userData = new UserModel(req.body);
let employmentData = new EmploymentModel(req.body);
This will save all the parameters from req.body matching the schema
const Schema = mongoose.Schema;
const bcrypt = require('bcrypt-nodejs');
const crypto = require('crypto')
const Userschema = new Schema({
email:{
type:String,
unique:true,
lowercase:true
},
name:String,
password:String,
picture:String,
isSeller:{type:Boolean,default:false},
address:{
addr1:String,
addr2:String,
city:String,
state:String,
country:String,
postalCode:String
},
created:{type:Date,default:Date.now}
});
// this pre function do encryption before saving the password into database
Userschema.pre('save',async function(next){
var user =this;
console.log(user.password);
if (!user.isModified('password')) {
return next();
}
bcrypt.hash(user.password,null,null,(err,hash)=>{
if (err) {
return next(err);
}
user.password = hash;
next();
**this is my mistake I miss "next()"**
})
})
Related
Now I am using clmtrackr library to detect emotions from the webcam and I want to save this emotions Here is my node.js code to save the values in mongodb
exports.storeemotion = function (emotions, callback){
var eshema= new emotioncollection({
emotions: [emotions]
});
eshema.save(function(err) {
});
callback({"status":"emotion remote done"});
}
and the schema code is
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//var bcrypt = require('bcrypt-nodejs');
// search results schema
var ResultaSchema = new Schema({
emotions:[{emotion: String, value: String}]
});
module.exports = mongoose.model('emotioncollection',ResultaSchema);
emotions should be like that (check this image).
but the mongo saved an empty array (check this image).
The emotions parameters of your storeemotion function is already an array, so you just have to pass that parameters as is, not in another array:
exports.storeemotion = function (emotions, callback) {
var eshema = new emotioncollection({
emotions: emotions // <= your schema already expects an array of objects
});
eshema.save(function(err) {
if (err) return callback({"status": "error"});
callback({"status": "emotion remote done"});
});
}
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var Comment = mongoose.model('Comment', new Schema({
title : String,
body : String,
date : Date
}))
var Post = mongoose.model('Post', new Schema({
comments : [Comment]
}))
module.exports.Comment = Comment
module.exports.Post = Post
Followed a tutorial for a simple app, and while trying to create something else off of it and learning about Mongoose schemas I get an error trying to use embedded documents with the way the previous app defined models
I'm getting this error
throw new TypeError('Undefined type ' + name + ' at array `' + path
+
TypeError: Undefined type model at array comments
To embed a document you need to pass its schema in the referencing document. For that, you can separately store the schema in variable as an intermediate step and later use it to define model.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var CommentSchema = new Schema({
title : String,
body : String,
date : Date
});
var PostSchema = new Schema({
comments : [CommentSchema]
});
module.exports.Comment = mongoose.model('Comment', CommentSchema);
module.exports.Post = mongoose.model('Post', PostSchema);
In my web application when the user logs in they should see all the documents they made. However when I test my application, I see all the documents including the ones that I didn't make. I believe this is because I am not using Parse.query.equalTo correctly.
Here is my code:
router.post('/login', function (req, res) {
var tempname = req.body.username;
var username = tempname.toLowerCase();
var password = req.body.password;
var login = Promise.promisify(Parse.User.logIn);
var promerror = Promise.reject("error");
var Files = Parse.Object.extend("File");
var query = new Parse.Query(Files);
query.include('user');
var finds = query.find;
var doc = {};
var name, url;
return login(username, password).catch(function (error) {
}).then(function (user, error) {
query.equalTo("user", Parse.User.current());
console.log(JSON.stringify(Parse.User.current()));
if (user) {
res.render('logins', { Message: "Username and/or password don't match" });
}
var temp;
}).catch(function (err) {
res.render('logins');
}).then(query.find(function (results) {
for (var i = 0; i < results.length; i++) {
var object = results[i];
var userID = object.get('user');
console.log("current user");
var codefile = object.get('javaFile');
temp = codefile.name();
name = temp.split("-").pop();
url = codefile.url();
doc[name] = url;
}
})).catch(function (error) {
promerror(error);
}).finally(function () {
res.render('filename', { title: 'File Name', FIles: JSON.stringify(doc) });
}).done();
});
When the user logs in, it should go to the database retrieve all the documents the user made, and save it to doc, the doc is then send to the client side to be displayed.
here is the code for user saving a file:
newFile.save({ user: Parse.User.current(), fileName: newnames, javaFile: parseFile })
I'm not sure, but try setting the File user field to the object id instead of the user object itself. Parse objects sometimes will return a pointer, sometimes the id, etc. So you might be getting unexpected behavior where you're setting the field to Parse.User.current(). Besides that, you look like you're using equalTo correctly.
Otherwise, basically the only way to debug cloud code is to console.log and view the logs.
As a side note, you should be setting the ACL of each File before you save it... that way, a user wouldn't be able to view another user's files anyway (unless these files are meant to be public).
I am using Nodejs Express. I currently have a script that produces an array of objects from Google API. I need to take that JSON data and use it in my templates. How can I call the function in my script from my route file?
This is my script file:
var Spreadsheet = require('edit-google-spreadsheet');
Spreadsheet.load({
debug: true,
spreadsheetId: '1eWmSV4Eq-se4gZSvBfW-J-lEOLwNopEfMavZByJ-qD8',
worksheetId: 'owrromd',
// 1. Username and Password
username: 'user',
password: 'pass',
}, function sheetReady(err, spreadsheet) {
//use speadsheet!
spreadsheet.receive(function(err, rows, info) {
if (err) throw err;
var announcementArray = [];
//console.log(rows);
for (x in rows) {
var eachObject = rows[x]
var side = eachObject['1'];
//console.log(side);
var type = eachObject['2'];
//console.log(type);
var announcement = eachObject['3'];
//console.log(announcement);
var announcementItem = {};
announcementItem.side = side;
announcementItem.type = type;
announcementItem.announcement = announcement;
announcementArray.push(announcementItem);
}
announcementArray.shift();
console.log(announcementArray);
});
});
This is my route js file:
module.exports=function(app){
app.get('/', function(req,res){
res.render('index', {title:"Home page", description:"The is the description"});
});
}
Change the content of the script file, let's call it loadSheet.js
var Spreadsheet = require('edit-google-spreadsheet');
function loadSheet() {
Spreadsheet.load({
debug: true,
spreadsheetId: '1eWmSV4Eq-se4gZSvBfW-J-lEOLwNopEfMavZByJ-qD8',
worksheetId: 'owrromd',
// 1. Username and Password
username: 'user',
password: 'pass',
}, function sheetReady(err, spreadsheet) {
//use speadsheet!
spreadsheet.receive(function(err, rows, info) {
if (err) throw err;
var announcementArray = [];
//console.log(rows);
for (x in rows) {
var eachObject = rows[x]
var side = eachObject['1'];
//console.log(side);
var type = eachObject['2'];
//console.log(type);
var announcement = eachObject['3'];
//console.log(announcement);
var announcementItem = {};
announcementItem.side = side;
announcementItem.type = type;
announcementItem.announcement = announcement;
announcementArray.push(announcementItem);
}
announcementArray.shift();
console.log(announcementArray);
});
});
}
//Export it to module
exports.loadSheet = loadSheet;
Then in the route js:
var ls = require('./loadSheet.js'); //Load the module, get the name of the script file
app.get('/', function(req,res){
res.render('index', {title:"Home page", description:"The is the description"});
ls.loadSheet();
});
So you'd adapt the module the other response created. But you are going to need to give a callback to loadSheet. I am cutting out the main body of that function for clarity.
var Spreadsheet = require('edit-google-spreadsheet');
function loadSheet(theCallback) { //take a callback here.
Spreadsheet.load({...yourdata...}, function sheetReady(...) {
// create your announcementArray
// then call the callback
theCallBack(undefined,announcementArray);
});
});
}
//Export it to module
exports.loadSheet = loadSheet;
Then, from your routes, you can get it like so:
var ls = require('./loadsheet.js'); // assumes in same dir as routes
app.get('/', function(req,res){
ls.loadSheet(function(err,result){
res.render('myTemplate',result);
});
});
I am going to assume you can take care of getting the result data into your template. You can look in the index template to see how it pulls in the data. I don't know whether you are using Jade or EJS.
Note, this is all sort of hackish but addresses your functional question. Let me know if you need a little further direction.
I just started learning with API. And I'm stumbling upon this problem.
MY GOAL: I would love to make two separate calls to marvel API at the same time. The first call will get all the data about the character and its id then I bundle them together inside a variable and save it in the database. Now, the second call will get all the comics data and these data will be embeded to the character object that was created during the first call. Now that I have this complete character variable. I can then send it to the view engine. But I do not know how to do it. Is there a simpler way to tackle this problem ?? Can you guys please let me know what I am doing wrong here...
//Mongoose model set up for Thumbnail > path, and extension
var Schema = mongoose.Schema;
var thumbnailSchema = new Schema({
path: "String",
extension: "String"
});
var thumbnailPath = mongoose.model('thumbnailPath', thumbnailSchema);
//Mongoose model set up for Comics
var Schema = mongoose.Schema;
var comicsSchema = new Schema({
title: "String",
imagePath: [thumbnailSchema]
});
var Comics = mongoose.model('Comics', comicsSchema);
//Mongoose model set up for Character
var Schema = mongoose.Schema;
var characterSchema = new Schema({
id: "Number",
name: "String",
description: "String",
imagePath: [thumbnailSchema],
comicsPath: [comicsSchema]
});
var Character = mongoose.model('Character', characterSchema);
//Create POST
app.post('/', function(request,response){
var characterData = request.body.character;
var url = "https://gateway.marvel.com/v1/public/characters?name=" + characterData + "&ts=thor&apikey=PRIVATe"
Request(url,function(error,res,body){
var apiData = JSON.parse(body)
if(!error && res.statusCode == 200){
var newCharacter = Character ({
id: apiData.data.results[0].id,
name: apiData.data.results[0].name,
description: apiData.data.results[0].description
});
newCharacter.imagePath.push({
path: apiData.data.results[0].thumbnail.path,
extension: apiData.data.results[0].thumbnail.extension
});
} else {
var characterID = newCharacter.id
var comicsURL = "https://gateway.marvel.com/v1/public/characters/" + characterID + "/comics?limit=5&ts=thor&apikey=PRIVATE";
Request(comicsURL,function(error,res,body){
if(!error && res.statusCode == 200){
var comicsData = JSON.parse(body)
var newComics = Comics({
title: comicsData.data.results[0].title,
});
newComics.imagePath.push({
path: comicsData.data.results[0].thumbnail.path,
extension:comicsData.data.results[0].extension
});
newCharacter.imagePath.push({newComics})
console.log(newComics);
}
})
}
})
});
Everyone... I manage to take this one down by using a request-promise https://github.com/request/request-promise library. Now, with the searched character from the API as well as the comics front together. I can save it into a variable then take it to the database to store; that is happening in the background. With that finish, we can then hopefully pass it over successfully (will see) to the template engine to view. For future references......
code code2