Mongoose - Redefining schema structure - node.js

I have the following code:
var Schema = mongoose.Schema;
var personSchema = new Schema({
firstname: String,
lastname: String,
address: String,
});
var Person = mongoose.model('humans', personSchema);
var john = Person({ //will turn into a new object.
firstname: "john",
lastname: "doe",
address: "somewhere",
});
//save the user
john.save(function(err){
if(err) throw err;
console.log('person saved!');
});
now, in my database, I have a collection called humans with
firstname: "john",
lastname: "doe",
address: "somewhere",
as you can see above. My question is: is there a way that inside the humans collection, there will be 1 document that will have the structure you see above, and one with some new fields:
firstname: String,
lastname: String,
address: String,
car: String,
office: String
I have tried a couple of ways to redefine the structure of the personSchema
but it's always giving me the same error, Cannot overwrite model once compiled.”
Thank you for your time.

The error is occurring because you already have a schema defined, and then you are defining the schema again. Instantiate the schema once and the make Global object to access schema.
Change your Person schema, and add new fields
var personSchema = new Schema({
firstname: String,
lastname: String,
address: String,
car: String,
office: String
});
Documents which does not contain added fields after populating will have this keys but with undefined values.
For not ignoring new properties you can unstrict schema
var personSchema = new Schema({
firstname: String,
lastname: String,
address: String,
car: String,
office: String
}, {strict: false});
Also you can use Mixed type to set anything to property
var personSchema = new Schema({
firstname: String,
lastname: String,
additional: Mixed
});
And set other properties in additional field.

Related

How to delete the data across the collections

Let's say, I have collections like
let employee = mongoose.Schema({
name: String,
email: String,
department: String,
doj: Date,
address: String
});
let student= mongoose.Schema({
name: String,
email: String,
department: String,
doj: Date,
address: String
});
let manager= mongoose.Schema({
name: String,
email: String,
department: String,
doj: Date,
address: String
});
in my database. I need to delete every data which has department "Computer Science" in each collection(employee, student, manager). I don't know how to do it. I tried deleting data by getting collection names from my database first then querying to remove each data as I said, but it doesn't work as I expected, always return error"db.getCollectionName is not a function". Any idea how to remove data across the multiple collections at the same time?. I am using node js,express and MongoDB.
To delete matching records for all collections, you can loop through all the models you have registered with Mongoose.
Object.keys(connection.models).forEach(async(collection) => {
const usersss = mongoose.model(collection)
await usersss.deleteMany({ defaultAccountId: userParam.defaultAccountId, grnNo: userParam.grnNo })
})

Creating different types of users in mongodb

I want to create an API to register, login and other things. two types of users
A teacher and a student , I'm using MongoDb and defining the schema.
const UserSchema = new Schema({
studentInfo : {
name: String,
email: String,
password: String,
birthday: Date,
state: String,
zip_code: String,
address: String,
phone_number: String,
},
teacherInfo : {
name: String,
email: String,
password: String,
birthday: Date,
state: String,
zip_code: String,
address: String,
phone_number: String,
course: {
title: String,
price: Number,
description: String
}
},
role: String
});
is this a good approach? or there is a better way?
I added the role field to perform route guarding on the front end.
I'm using Nodejs and Express.
any help will be much appreciated, thank you.
This is one way of embedding both student and teacher object in the same document and you can simply get data with single query. Although you don't need to separately embed the common fields in object like name, email, password, phone_number etc. teacherInfo would be like this
teacherInfo : {
course: {
title: String,
price: Number,
description: String
}
}
You can create different schemas for student and teacher (as they are unique and you might need them independent sometimes), and make User as the base model.
var User= new Schema({
name: String,
email: String,
password:String,
birthday: Date,
state: String,
zip_code: String,
address: String,
phone_number: String,
_teacher:{type:Schema.Types.ObjectId, ref:'Teacher'},
_student: {type:Schema.Types.ObjectId, ref:'Student'}
});
If _teacher has a value then the user can be considered as a teacher.
If _student has a value then the user can be considered as a student.
//Teacher Model
var Teacher = new Schema({
course: {
title: String,
price: Number,
description: String
},
//other teacher's fields
})
//Student Schema
var Student= new Schema({
//student's fields if you need in future
})

Mongoose Ref User Object

I hope everyone learning something today. I need some help. I have a Gift model which looks something like this:
let giftSchema = new mongoose.Schema({
gift: String,
date: {
type: Date
},
giftDescription: String,
giftAmount: String,
giftCode: String,
redeemCode: String,
passCode: String,
senderFirstName: String,
senderLastName: String,
giftMessage: String,
user: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
username: String
}
});
module.exports = mongoose.model('Gift', giftSchema);
This is my user model:
const mongoose = require('mongoose'),
passportLocalMongoose = require('passport-local-mongoose');
let UserSchema = new mongoose.Schema({
firstName: String,
lastName: String,
alaisFirstName: String,
alaisLastName: String,
username: String,
password: String,
isAdmin: Boolean,
addressLine1: String,
addressLine2: String,
city: String,
state: String,
zipCode: String
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model('User', UserSchema);
I have pretty much 2 users, and no guest. The admin sends gifts to a user. So as an admin, on the new route, I need to send something to the user. However, in my field: for ( think gmail search field ) I will be searching for either firstName, lastName, alaisFirstName, and alaisLastName than sending the gift to the user.
How could I model that? I cant do it by type: mongoose.Schema.Types.ObjectId, because the admin is the one sending it to the user, but I want something similar to that.

Error while defining mongoose schemas

I am new to mongo and mongoose. I am trying to create 3 collections Users, Articles and Comments. I want the users documents should contain articles that users have saved. The articles object should have users and comments as embedded objects and comments should have embedded user objects.
I want this to be done using the ids of the individual objects so that I can reduce the loading time, but could not find a suitable way to do so using mongoose. Please suggest how should I proceed with the Schema implementation.
var UserSchema = new mongoose.Schema({
name: String,
email: String,
profilePicture: String,
password: String,
readingList: [articleSchema]
});
var commentsSchema = new mongoose.Schema({
content: String,
votes:{
up:[UserSchema],
down:[UserSchema]
},
comments:[commentsSchema],
timestamp:Date.now
});
var articleSchema = new mongoose.Schema({
title: String,
content: String,
image: String,
votes:{
up: [UserSchema],
down: [UserSchema]
},
comments:[commentsSchema],
timestamp: Date.now
});
What you have is failing because articleSchema isn't defined when you're using it in the UserSchema. Unfortunately, you can reverse the order of defining the schema because they're dependent on each other.
I haven't actually tried this, but based on some quick googling there is a way to create the Schema first and then add the properties.
var UserSchema = new mongoose.Schema();
var CommentsSchema = new mongoose.Schema();
var ArticleSchema = new mongoose.Schema();
UserSchema.add({
name: String,
email: String,
profilePicture: String,
password: String,
readingList: [ArticleSchema]
});
CommentsSchema.add({
content: String,
votes:{
up:[UserSchema],
down:[UserSchema]
},
comments:[CommentsSchema],
timestamp:Date.now
});
ArticleSchema.add({
title: String,
content: String,
image: String,
votes:{
up: [UserSchema],
down: [UserSchema]
},
comments:[CommentsSchema],
timestamp: Date.now
});

How to reference another schema in my Mongoose schema?

I'm building a Mongoose schema for a dating app.
I want each person document to contain a reference to all the events they've been to, where events is another schema with its own models in the system. How can I describe this in the schema?
var personSchema = mongoose.Schema({
firstname: String,
lastname: String,
email: String,
gender: {type: String, enum: ["Male", "Female"]}
dob: Date,
city: String,
interests: [interestsSchema],
eventsAttended: ???
});
You can do so by using Population
Population is the process of automatically replacing the specified
paths in the document with document(s) from other collection(s). We
may populate a single document, multiple documents, plain object,
multiple plain objects, or all objects returned from a query.
Suppose your Event Schema is defined as follows:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var eventSchema = Schema({
title : String,
location : String,
startDate : Date,
endDate : Date
});
var personSchema = Schema({
firstname: String,
lastname: String,
email: String,
gender: {type: String, enum: ["Male", "Female"]}
dob: Date,
city: String,
interests: [interestsSchema],
eventsAttended: [{ type: Schema.Types.ObjectId, ref: 'Event' }]
});
var Event = mongoose.model('Event', eventSchema);
var Person = mongoose.model('Person', personSchema);
To show how populate is used, first create a person object,
aaron = new Person({firstname: 'Aaron'})
and an event object,
event1 = new Event({title: 'Hackathon', location: 'foo'}):
aaron.eventsAttended.push(event1);
aaron.save(callback);
Then, when you make your query, you can populate references like this:
Person
.findOne({ firstname: 'Aaron' })
.populate('eventsAttended') // only works if we pushed refs to person.eventsAttended
.exec(function(err, person) {
if (err) return handleError(err);
console.log(person);
});
To reference the ObjectId of one table in another table refer below code
const mongoose = require('mongoose'),
Schema=mongoose.Schema;
const otpSchema = new mongoose.Schema({
otpNumber:{
type: String,
required: true,
minlength: 6,
maxlength: 6
},
user:{
type: Schema.Types.ObjectId,
ref: 'User'
}
});
const Otp = mongoose.model('Otp',otpSchema);
// Joi Schema For Otp
function validateOtp(otp) {
const schema = Joi.object({
otpNumber: Joi.string().max(6).required(),
userId: Joi.objectId(), // to validate objectId we used 'joi-objectid' npm package
motive: Joi.string().required(),
isUsed: Joi.boolean().required(),
expiresAt: Joi.Date().required()
});
// async validate function for otp
return schema.validateAsync(otp);
}
exports.Otp = Otp;
exports.validateOtp = validateOtp;
List item
var personSchema = mongoose.Schema({
firstname: String,
lastname: String,
email: String,
gender: {
type: String,
enum: ["Male", "Female"]
}
dob: Date,
city: String,
interests: [interestsSchema],
eventsAttended[{
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Place"
}],
**//ref:"Places"...you have put the other model name**
*OR*
eventsAttended[{
type: mongoose.Types.ObjectId,
required: true,
ref: "Place"
}],
});

Resources