Can I access multiple schemas with Mongoose? - node.js

could someone please give me a suggestion? My schema example looks like this:
const eventSchema = new Schema({
eventName : String,
date: Date,
location: String,
role: [],
task:[],
});
const userSchema = new Schema({
email: { type: String, unique: true, lowercase: true },
password: String,
eventList: [eventSchema],
});
I'm even wondering about creating a 3rd schema and put it into the eventSchema. Do you think it's possible to work on?
So far, I only access the userSchema through
const ModelClass = mongoose.model('user', userSchema);
module.exports = ModelClass;
Could I somehow export the other schemas and access them directly at the same tiem? How is that done? Thanks a lot in advance!

Multiple Schema's in Mongoose is perfectly possible. The best approach I've seen is to create each schema in a separate file (so you can export each one). Then you can import and consume them anywhere you need.

Related

Foreign Key relationship in Mongoose with customized key

I am kinda new to MongoDB and nextjs space. I have 2 schemas :
User
Fav Dishes
Schema for user is :
import mongoose from 'mongoose'
require('mongoose-type-url');
const UserSchema = new mongoose.Schema({
name: { type: String, unique: true}
address: {type: String},
},{ timestamps: {} })
UserSchema.pre("save", function (next) {
let brand = this;
user.name = user.name.replace(/ /g,"_")
next();
})
Another schema is
const FavDish = new mongoose.Schema({
name: String,
user: {type: mongoose.Schema.Types.ObjectId, ref : 'User'})
So the reference in FavDish collection want to use is userName instead mongo created ObjectID. and while populating the data for FavDish get the details for user as well. How can i achieve this? please help me.
So, first of all, if the relationship between the Schemas are 1to1, consider embedding the favDish inside the user Schema and not referencing (each user has a name, an address and a favDish name).
So the userSchema will look like:
const UserSchema = new mongoose.Schema({
name: { type: String, unique: true}
address: String,
fevDish: String
},{ timestamps: {} })
If you want to keep it like the way you wanted (with two schemas and referencing) you will need to populate after finding the fevDish:
const populatedDish = await FavDishModel.findOne({name: 'pasta'}).populate('user');
/**
* populatedDish - {
* name: 'pasta',
* user: {
* name: 'Justin',
* address: 'NY'
* }
* }
*
*/
this way while finding the dish you want, mongoose will put the user object instead of the _id of it.
Hope that helps.

Data modeling in mongoose

I'm creating my website with node.js(express.js) and I have one question about mongodb and mongoose.
This question is how to make schema for my collection? For example I have users on my webiste, and user can subscribe for another user? How to write schema for this?
For now I have something like this:
userSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true }
});
This line will allow you to add things to the database via the schema. (Very idiomatically, the database will be called 'users', as Mongoose pluralises the first argument for you.)
mongoose.model('user', userSchema);
There are a couple of ways to add things to the database - I use promises, which requires you to call this before you connect (I think it has to be before?)
mongoose.Promise = Promise;
You can then save new instances of the schema:
new User ({
username: 'me',
password: 'dontlooknow',
}).save()
Save returns a promise, so you can follow it with a .then() after if you want. You can do it with callbacks too if you prefer, just look at the docs. http://mongoosejs.com/docs/guide.html.

Whats the proper way to use mongoose population?

I have two schemas setup:
var ClientSchema = new Schema({
name: String
});
module.exports = mongoose.model('Client', ClientSchema);
And
var PlaceSchema = new Schema({
client: {type: mongoose.Schema.Types.ObjectId, ref: 'Client'},
address: String
});
module.exports = mongoose.model('Place', PlaceSchema);
If i get a list of places, i can populate the client easily like this:
Place.find({}).populate('client')
However, if i want to get a list of all the clients and all of their places, how would i make a query for that? Should i just simply loop through all of the clients and finding the places for it with Place.find({client:client._id) before returning the response?
Well if you have a number of places they will have their own unique ids, and for every place a client is connected to, you can have an array of placeId, you can push a placeId to this array everytime a client is connected to this place.`
var ClientSchema = new Schema({
name: String,
_address: [{type: mongoose.Schema.Types.ObjectId, ref: 'Place'}]
});`
This data structure would only work in one way, PlaceSchema do refer to ClientSchema but ClientSchema do not have any reference to PlaceSchema, the solution would be to define your ClientSchema this way :
var ClientSchema = new Schema({
name: String,
_address: [{type: mongoose.Schema.Types.ObjectId, ref: 'Place'}]
});
It seems kinda dumb but it would be much easier for your case

How to reference a Mongoose Schema that hasn't been registered yet

This question is similar to: this question
Working with Mongoose, I have something like the following code. (I've prefixed the files with numbers, so I can load them in the order they appear in the 'models' directory, but still control the loading order.)
In 100-employee.server.model.js:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var EmployeeSchema = new Schema({
name: {
type: String,
default: ''
},
company: {
type: Schema.ObjectId,
ref: 'Company'
},
subordinates: [EmployeeSchema],
});
mongoose.model('Employee', EmplyeeSchema);
Then, in 200-company-server.js, I have:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var CompanySchema = new Schema({
name: {
type: String,
default: ''
},
CEO: {
type: Schema.ObjectId,
ref: 'Employee'
}
});
mongoose.model('Company', CompanySchema);
Obviously, this doesn't work, since Company is referenced before it is registered. And, loading these in the opposite order doesn't work for the same reason. What I need, is a logical data structure like:
{
name: 'Acme, Inc',
CEO: {
name: 'Karen',
subordinates: [{
name: 'Bob',
subordinates: [{
name: 'Lisa',
subordinates: []
},
name: 'Jerry',
subordinates: []
}]
}]
}
}
(I think I got all of my brackets in place. I just typed that JSON to illustrate the need.)
I could just use an ObjectId for 'company' in EmployeeSchema, but it doesn't fix the problem. I still get a complaint that Company hasn't been registered.
Someone will ask for the use case, so here it is:
I have a bunch of companies.I have a hierarchy of employees of a company. And, I've got a bunch of companies. For each company, I need to know the CEO, without having to search all of my employees for the one with no parent, that has an ObjectId ref Company, but that still runs into the same problem.
Any suggestions?
OK, I've come up with an answer, or at least a workaround. Doesn't feel very elegant. In fact I actively dislike it, but it works. Would love to see a better solution. In 100-company-server.js, define the parent entity first, like so:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var CompanySchema = new Schema({
name: {
type: String,
default: ''
},
CEO: {
name: { // This is the company name, so probably a bad example
type: String,
default: ''
}, {
shoeSize: Number
}, etc ...
}
});
mongoose.model('Company', CompanySchema);
The key thing to notice here is that instead of making CEO an ObjectId ref 'Employee' I supplied an object that uses the same properties as my Employee schema. Depending on how you want to use it, you may have to coerce that into an Employee object in the controller. Or, there might be a clever way to use a virtual to do the same thing (http://mongoosejs.com/docs/guide.html) But, the virtual would just have to be defined AFTER the EmployeeSchema and model.
In 200-employee.server.js, something like the following:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
CompanySchema = mongoose.model('Company').schema; // so you can use this
// after your Employee
// is defined
var EmployeeSchema = new Schema({
name: {
type: String,
default: ''
},
company: {
type: Schema.ObjectId,
ref: 'Company'
},
subordinates: [], // Just an empty array. You fill it with Employees in the controller. You could use a virtual to do the same thing, probably.
});
mongoose.model('Employee', EmployeeSchema);
So, it's kind of ugly, but it works.
Key points:
In defining CompanySchema, you don't use an ObjectId ref 'Employee'.
Instead, you define an object that looks like a Company object.
Since this object doesn't have an _id, you have to work around that in the
controller. In my case, this works fine. But, for many/most use cases, this
probably would not. You'd have to work around this with clever virtuals
and/or the controller.
Use a simple array, without type, to store your children (suborinates in
this example.
The array works just fine, and returns objects just as if you used an array
of ObjectId ref Employee.
Making the Company refer to an Employee (which hasn't been defined yet), you
have to convert a generic object into an Employee object. But, there are
many ways to do that.
There is, undoubtedly, a better way to do this.

Node.js and mongoose module.exports on a model vs Schema

I have been following many tutorials concerning the MEAN stack, and I have come to a question I've found hard to answer (note: I found a possible duplicate when searching, but don't believe it answers my question)
Take this code for example, which can be found here
// app/models/nerd.js
// grab the mongoose module
var mongoose = require('mongoose');
// define our nerd model
// module.exports allows us to pass this to other files when it is called
module.exports = mongoose.model('Nerd', {
name : {type : String, default: ''}
});
After finishing the tutorial, I rewrote the code to attempt to replicate the lessons like so ("menu item" for a restraunt):
var mongoose = require('mongoose');
module.exports = mongoose.model('Item', {
name: {type: String, required: true},
description: {type: String, require: true},
price: {type: String, required: true},
ingredients: [{
name: {type: String, default: ''},
amt: {type: String, enum: ['None', 'Reg', 'XTRA'], required: true}
}]
});
I will be using an interface to create new menu items. Should I leave the code as is, or use a Schema?
Well. I was reading through code to post as an example for a difference, and came to this.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BearSchema = new Schema({
name: String
});
module.exports = mongoose.model('Bear', BearSchema);
I then noticed that the schema was defined inline (I think?) instead of being declared. I would assume that this is because later, it will be much cleaner for me to add more schema declarations in this model, along with methods. If anyone can provide me with clarification, I'll give you the answer!

Resources