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);
Related
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()"**
})
})
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"});
});
}
The error message:
MissingSchemaError: Schema hasn't been registered for model "User".
Use mongoose.model(name, schema)
at Mongoose.model (/Users/JimBarrows/Desktop/TaskVelocity/cucubmer/node_modules/mongoose/lib/index.js:349:13)
at Object.<anonymous> (/Users/JimBarrows/Desktop/TaskVelocity/cucubmer/features/support/hooks.js:3:21)
My world.js file:
/**stuff**/
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
require('../../../public_ui/models/Users');
var User = mongoose.model('User');
mongoose.connect('mongodb://192.168.99.100:27017/task_velocity');
As I understand it, this should setup mongoose quite nicely. Then in hooks.js:
'use strict';
var mongoose = require('mongoose');
var User = mongoose.model('User');
I've tried, in the hooks.js file:
'use strict';
var mongoose = require('mongoose');
require('../../../public_ui/models/Users');
var User = mongoose.model('User');
but that gives me the same error when I try to get ahold of the model.
Any ideas on what I'm doing wrong?
Jim Barrows, considering that the error is:
MissingSchemaError: Schema hasn't been registered for model "User".
and that your world.js has the following lines:
require('../../../public_ui/models/Users');
var User = mongoose.model('User');
I believe that is just a typo error and you could fix it easily by doing the following:
var User = mongoose.model('Users'); // instead of var User = mongoose.model('User');
**which by the way is exactly what dafyk commented in your post (not an answer) some days ago...
Hope this helps
I'm not sure, but...
check this link
You have to make schema and set mongoose.model('User',schema);
Can you show me "Users.js" source?;
If you want make module,
like this source
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String,
passwrod: String
//Have to Custom
});
module.exports = mongoose.model('User', UserSchema);
and use this
var Users = require('../../../public_ui/models/Users');
I'm working in nodejs with Mongoose, at this moment I have data in different collections with _id like string writing for the user, I try to make a refactor of this and generate _id automatically.
I want have in other file js only function generateID( return _id; ); and implement this function in all models without write over and over in all models.
This is bus.js
/***********************************Bus Model**********************************/
var mongoose = require('mongoose'),
merge = require('merge'),
global = require('./schema/global');
/***********************************Schema******************************************/
var Schema = mongoose.Schema;
var busSchema = new Schema({});
/***********************************Methods*****************************************/
var bus = mongoose.model('Bus', busSchema);
/**
* extend functions from global
* we do this to prevent duplicate code
*/
merge(bus.schema.methods, global.schema.methods);
module.exports = bus;
And this is global.js in schema folder over models folder in project
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var globalSchema = new Schema({});
function objectIdAsString() {
return mongoose.Types.ObjectId().toString();
}
globalSchema.methods.objectIdAsString = objectIdAsString;;
module.exports = mongoose.model('global', globalSchema);
And in route.js have this implementation:
var bus = new Bus();
bus._id = bus.objectIdAsString();
Solution is creating a Mongoose plugin
http://mongoosejs.com/docs/plugins.html
global.js
var mongoose = require('mongoose');
module.exports = exports = function objectIdAsString(schema) {
schema.methods.objectIdAsString = function objectIdAsString() {
return mongoose.Types.ObjectId().toString();
};
}
bus.js
/***********************************Bus Model**********************************/
var mongoose = require('mongoose'),
merge = require('merge'),
global = require('./schema/global');
/***********************************Schema******************************************/
var Schema = mongoose.Schema;
var busSchema = new Schema({});
/**
* extend functions from global
* we do this to prevent duplicate code
*/
busSchema.plugin(global);
module.exports = mongoose.model('Bus', busSchema);
Somewhere else:
var bus = new bus();
console.log(bus.objectIdAsString());
Is working and outputting the correct values for me:
566b35a02a54c60e168c3a9f
566b35a02a54c60e168c3aa1
566b35a02a54c60e168c3aa3
.....
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