How can i generate child model in mongoose - node.js

I'm trying to model the following.
I have a parent model that is called Brick that has some attributes.
There will be 5+ type of bricks that will all have their own specific attributes wich are needed also.
I want to be able to select all Bricks of a certain custumer id later, whatever the type (TwitterBrick, facebookBrick et cetera) is.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// set up a mongoose model
module.exports = mongoose.model('Brick', new Schema({
type: String,
userid: { type: String, required: true},
animationspeed: { type: Number, min: 1, max: 100 },
socialsite: String, // none, twitter, instagram
socialsearchtags: String,
tagline: { type: String, minlength:3,maxlength: 25 },
}));
An example for a child is TwitterBrick.
for now it is:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('TwitterBrick', new Schema({
bgColor1: String,
bgColor2: String,
bannerBgColor1: String,
bannerBgColor2: String,
}));
TwitterBrick should inherit the attributes of Brick , but i don't know how..
Can you help me in the right direction?
Thanks!
Steven

My solution was to set a new "content" field in brickSchema, and split in different files:
brick.schema.js
var mongoose = require('mongoose');
module.exports = {
type: String,
userid: { type: String, required: true},
animationspeed: { type: Number, min: 1, max: 100 },
socialsite: String, // none, twitter, instagram
socialsearchtags: String,
tagline: { type: String, minlength:3,maxlength: 25 },
content: {type:mongoose.Schema.Types.Mixed, required: false, default: null}
}
brick.model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BrickSchema = new Schema(require('brick.schema.js'));
module.exports = mongoose.model('defaultBrick', BrickSchema, 'Bricks');
twitterBrick.model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var brickSchema = require('brick.schema.js');
brickSchema.content = new Schema({
bgColor1: String,
bgColor2: String,
bannerBgColor1: String,
bannerBgColor2: String,
});
var BrickSchema = new Schema(require('brick.schema.js'));
module.exports = mongoose.model('twitterBrick', BrickSchema, 'Bricks');
Hope it helps !

Just add the Brick model as an attribute (composition).
It will compensate for that.
Or just rely on exisiting mongoose plugins for that https://github.com/briankircho/mongoose-schema-extend
check this one out.

That's because you didn't "require" the previous file, so technically it's out of scope and the TwitterWallBrickSchema doesn't have a clue what's a "BrickSchema".
Either you put the two models in the same file , or require the first file in the second file.

Related

Require one field, if another doesn't exists

To post a message to MongoDB i need to send a schema with a required text field. But even media field exists (as optional) - you can send request without text field. How should I do it? Here is a code:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var Message = new Schema({
text: {type: String, required: true},
media: {type: Object, required: false}
})
You can try this using function validation as mentioned here
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var Message = new Schema({
text: {
type: String,
required: function() {
return !this.media;
}
},
media: {
type: Object,
required: function() {
return !this.text;
}
})

Error when using _id as a property type in a Mongoose Schema

I am learning MongoDB and mongoose at the moment. I have a Archive and a User schema in mongoose:
archive.js
var mongoose = require('mongoose');
var User = require('../users/user');
var notesSchema = new mongoose.Schema({
author: User.userId,
text: String,
files:[String]
});
var archiveSchema = new mongoose.Schema({
name: String,
priority: String,
deadline: Date,
status: String,
assigned_memnbers: [User.userId],
notes: [notesSchema],
});
archiveSchema.virtual('archiveId').get(function() {
return this._id;
});
module.exports = mongoose.model('Archive', archiveSchema);
user.js:
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
username: String,
mail: String,
bio: String,
password: String
});
userSchema.virtual('userId').get(function() {
return this._id;
});
module.exports = mongoose.model('User', userSchema);
When I run my server i get the error
TypeError: Invalid value for schema path `author`, got value "undefined"
The the problem comes from author: User.userId, but I don't know how to make a reference between the two tables.
For reference, here is what my complete db design more or less looks like:
Any input on how to solve this problem or improve the overall design is welcome. Thanks you.
I think what you're talking about is a reference to other collection:
author: { type: Schema.Types.ObjectId, ref: 'User' }
and
assigned_members: [{ type: Schema.Types.ObjectId, ref: 'User' }]
should work fine.
Source: Mongoose population
I faced the same issue.I had imported a module, It was just not exporting from another module. so I have added:
exports.genreSchema = genreSchema;

Mongoose : Error referencing sub schema

My user model
'use strict';
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
var UserSchema = new mongoose.Schema({
id: String,
username: String,
firstName: String,
lastName: String,
initials: String,
password: String,
age: Number,
dateJoined: Date,
contactNo: String,
email: String,
about: String,
groupId: Number,
adminMode: Boolean,
simpulPoints: Number,
})
//Define model for user
const User = {
UserModel: mongoose.model("user", UserSchema),
}
module.exports = {
UserSchema : UserSchema,
User : User
}
My Events Model
'use strict';
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
var UserSchema = require("../models/user").UserSchema
var EventSchema = new mongoose.Schema();
EventSchema.add({
id: String,
title: String,
description: String,
organizerId: String, //Simpul admin user responsible for event
startDate: Date, //MM-DD-YYYY HH:MM:SS:sssZ
endDate: Date,
group: String,
locaction: String,
googleMapsLink: String,
hasPassed: Boolean,
attendees: Number,
registeredUsers: [UserSchema],
groupId: Number,
adminMode: Boolean,
simpulAward: Number,
});
//Define model for evnt
var Event = {
EventModel : mongoose.model("event", EventSchema),
}
module.exports = {
Event : Event,
EventSchema : EventSchema
}
I'm getting the infamous "throw new TypeError('Invalid value for schema Array path" error with the 'registeredUsers' field. I've followed multiple posts with the same problem and can't seem to find where I am going wrong. According to my knowledge, I've exported the schemas appropriately. Any help/tips welcome
I ended up moving the Schema declarations out into a separate file and it seemed to do the trick. Suspect it must have been some file rights issue VSCode had with the users.js file

TypeError object is not a function

I'm developing an application in node.js with MongoDB
I have to files:
product.js and displaycost.js
this is product .js:
var mongoose = require('mongoose');
var Category = require('./category');
var productSchema = {
name:{type: String, require: true},
//Pictures mus start with "http://"
pictures:[{type:String, match: /^http:\/\//i}],
price:{
amount:{type: Number, required: true},
//ONly 3 supported currencies for now
currency:{
type: String,
enum:['USD','EUR','GBP'],
required: true
}
},
category: Category.categorySchema
};
var schema = new mongoose.Schema(productSchema);
var currencySymbols ={
'USD': '$',
'EUR':'€',
'GBP':'£'
};
/*
*
*/
schema.virtual('displayPrice').get(function(){
return currencySymbols[this.price.currency] +
'' + this.price.amount;
});
schema.set('toObject', {virtuals:true});
schema.set('toJSON', {virtuals:true});
module.exports = schema;
What I need is create a record with "productSchema"
I tried with this:
var Product = require('./product.js');
var p = new Product({
name: 'test',
price:{
amount : 5,
currency: 'USD'
},
category: {
name: 'test'
}
});
console.log(p.displayPrice); // "$5"
p.price.amount = 20;
console.log(p.displayPrice); //" $20"
//{... "displayPrice: "$20",...}
console.log(JSON.stringify(p));
var obj = p.toObject();
But when I run the displaycost.js throw me an error at the word "new"
and writes "TypeError: object is not a function"
I don't know why is happening that. Thank you.
you missing export mongoose model with model name.
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
Category = require('./category');
var productSchema = new Schema({
name: {type: String, require: true},
pictures: [{type: String, match: /^http:\/\//i}],
price: {
amount: {type: Number, required: true},
currency: {
type: String,
enum: ['USD', 'EUR', 'GBP'],
required: true
}
},
category: Category
});
var currencySymbols = {
'USD': '$',
'EUR': '€',
'GBP': '£'
};
productSchema.virtual('displayPrice').get(function () {
return currencySymbols[this.price.currency] +
'' + this.price.amount;
});
productSchema.set('toObject', {virtuals: true});
productSchema.set('toJSON', {virtuals: true});
module.exports = mongoose.model('Product', productSchema);
"new" can only be called on a function. not an object.
In program.js you are creating a new instance of the mongoose schema.
var schema = new mongoose.Schema(productSchema);
... more code ...
return schema;
In your other js file you require product. At this point in time product.js has returned an object to you. A new mongoose schema. It is an object which you are refering to as Product.
You then try to create a new instance of it by calling new on the product OBJECT. New cannot be called on an object literal. It can only be called on a function.
I don't believe you need to make a new instance of schema within product.js, just return the function that creates the schema. Then call new on it when you require it like you are in your second file.

How to create interdependent schemas in Mongoose?

I have two Schemas and I want them to interact with eachother. For instance:
// calendar.js
var mongoose = require('mongoose');
var Scema = mongoose.Schema;
var Day = mongoose.model('Day');
var CalendarSchema = new Schema({
name: { type: String, required: true },
startYear: { type: Number, required: true }
});
CalendarSchema.methods.getDays = function(cb){
Day.find({ cal: this._id }, cb);
}
module.exports = mongoose.model('Calendar', CalendarSchema);
// day.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var Calendar = mongoose.model('Calendar');
var DaySchema = new Schema({
cal: { type: ObjectId, required: true },
date: { type: Number, required: true },
text: { type: String, default: 'hello' }
});
DaySchema.methods.getCal = function(cb){
Calendar.findById(this.cal, cb);
}
module.exports = mongoose.model('Day', DaySchema);
However, I get an error because each schema depends on the other one. Is there a way to get this working using Mongoose? I include them like this:
// app.js
require('./models/calendar');
require('./models/day');
I realize this is an ancient thread, but I'm sure posting the solution will help others down the road.
The solution is to export the module before requiring the interdependent schemas:
// calendar.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CalendarSchema = new Schema({
name: { type: String, required: true },
startYear: { type: Number, required: true }
});
module.exports = mongoose.model('Calendar', CalendarSchema);
// now you can include the other model and finish definining calendar
var Day = mongoose.require('./day');
CalendarSchema.methods.getDays = function(cb){
Day.find({ cal: this._id }, cb);
}
// day.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var DaySchema = new Schema({
cal: { type: ObjectId, required: true },
date: { type: Number, required: true },
text: { type: String, default: 'hello' }
});
module.exports = mongoose.model('Day', DaySchema);
// same thing here. require after exporting
var Calendar = require('./calendar');
DaySchema.methods.getCal = function(cb){
Calendar.findById(this.cal, cb);
}
It really is that simple. Explanation by Brian Bickerton can be found here:
http://tauzero.roughdraft.io/3948969265a2a427cf83-requiring-interdependent-node-js-modules
It's nice to be able to use functions by name within a module instead of the lengthy module.exports.name. It's also nice to have a single place to look and see everything to be exported. Typically, the solution I've seen is to define functions and variables normally and then set module.exports to an object containing the desired properties at the end. This works in most cases. Where it breaks down is when two modules are inter-dependent and require each other. Setting the exports at the end leads to unexpected results. To get around this problem, simply assign module.exports at the top, before requiring the other module.
You need require the files. If they are in the same path do this:
//calendar.js
var Day = require('./day');
/* Other logic here */
var CalendarSchema = new Schema({
name: { type: String, required: true },
startYear: { type: Number, required: true }
})
, Calendar;
/* other logic here */
/* Export calendar Schema */
mongoose.model('Calendar', CalendarSchema);
Calendar = mongoose.model('Calendar');
exports = Calendar;
Do the same in day.js
EDIT: As JohnnyHK says this don`t work. Link to explanation

Resources