Combining Mongo Schemas - node.js

I have a MongoDB Schema to let users create an account using passport.js. It looks like this:
var UserSchema = new mongoose.Schema({
user: String,
password: String
});
I also have a JobsSchema that looks like this:
var JobSchema = new mongoose.Schema({
jobname: String,
score: Number,
});
Question: Is it possible to somehow add the "Jobs" Data to the User? I'd like to be able to access the jobs data by user... So for example I want to be able to show job data associated with a user like...
<%= user.jobName %>

You can store the job id in the user schema and use a populate() method to get the details of the job in the user object.
User:
var UserSchema = new mongoose.Schema({
user: String,
password: String,
job: {type: mongoose.Schema.Types.ObjectId, ref: 'Job'}
});
when you make a query, you should use populate() like:
db.users.find({}).populate('job');
So the response will be like:
response = {
user: 'Sam',
password: 123,
job: {
jobName: 'Manager',
score: 5
}
}
Now, you can access like : response.job.jobName
If you need the object path as user.jobname, then you could normalize the response manually by constructing a new object

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.

Nested objects are not update

Allora, I'm using mongoose for the first time and I decided to create 2 schemes: the first one represents a user and the second one represents his enquires. Users have an array of enquires like:
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [Enquire.schema] , "default" : [] },
});
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
I see that if I search for an enquire and update its status, it doesn't update the same enquire on the user's array, meaning that they are different object. I don't want to save an array of IDs as it will be the same as a relational database, so I see only 1 solution which is forgetting about the enquire scheme and use only the User scheme. Is it the way mongoose works? For every relationship do I have to insert everything like nested object?
I think you should use references to achieve what you want to achieve.
For more information on mongoose references and populate see Mongoose Populate documentation.
Try this, It may help you.
User Schema :
var userSchema = new mongoose.Schema({
name: String,
enquires: [{ type : mongoose.Schema.Types.ObjectId , ref : 'Enquiry' }]//array of enquiries
});
var User = mongoose.model('User',userSchema );
module.exports = User;
Enquiry Schema :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var Enquiry = mongoose.model('Enquiry',enquireSchema );
module.exports = Enquiry ;
Working :
create a new Enquiry.
Push it's ID(_id) into user's enquires array.
var enquiry = new Enquiry();
enquiry.enquire = "Dummy enquiry";//set the enquiry
enquiry.save(function(err,result){
if(!err){
//push 'result._id' into users enquires array
}
});
whenever you update an enquiry, it will be automatically updated in
user's document.
use populate to retrieve user's enquiries.
You can embed sub documents (entity) which has id and is like a document or embed native array like a normal property.
And I think the correct definition for yours is :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [enquireSchema] , "default" : [] },
});
If you use refs in embedded link then there are two separate collections and be like relational db's.

Store objects in array using mongodb, node and express

I'm trying to build a messaging system for my school project. I have created a schema in mongodb that looks like this:
var userSchema = new mongoose.Schema({
firstName: String,
lastName: String,
messages: []
});
I want to store an object in the messages that looks something similar to this:
{
from: 'fromUsername',
to: 'toUsername',
time: new Date(),
msg: 'message is here'
}
I want to be able to store that in the schema under the messages array. Is there a way to push that to the shcema? Not sure how to approach this task. Thanks!
You can define the schemas separately with the message schema embedded as part of the user document (as items within the messages array):
var messageSchema = new mongoose.Schema({
from: String,
to: String,
time: { type: Date, default: Date.now },
msg: String
})
var userSchema = new mongoose.Schema({
firstName: String,
lastName: String,
messages: [messageSchema]
});
mongoose.model('User', userSchema);
To add the given message to the messages array, follow the pattern:
// retrieve user model
var User = mongoose.model('User');
// create user instance
var user = new User({
firstName: 'Alice',
lastName: 'Bob'
});
// create a message
user.messages.push({
from: 'fromUsername',
to: 'toUsername',
msg: 'message is here'
});
You have an option to exclude the time field since you would have defined its default value when you persist your model.
user.save(function (err, user) {
if (!err) console.log(JSON.stringify(user, null, 4));
});
You can use th $push operator to appends your object value in the message array.
An example of how to use $push for your userSchema
// How to update a user already created
var User = mongoose.model('User');
User.update(
{ _id: id },
{ $push: {messages : {
from: 'fromUsername',
to: 'toUsername',
time: new Date(),
msg: 'message is here'}}
})

Accessing mongoose schema array with body-parser

Here is an example schema:
var schema = mongoose.Schema;
var userSchema = new schema ({
username: {type: String},
hobby: [{
indoor: {
type: {type: String},
description: {type: String}
},
outdoor: {
type: {type: String},
description: {type: String}
}
}]
});
module.exports = mongoose.model('User', userSchema);
So, a very simple schema. It asks for a user name, and then it asks for a user to list their hobbies, and is split between indoor and outdoor hobbies, and inside of an array.
Using body-parser, I could get to a user name in a form input like this:
var user = new User();
user.username = req.body.username;
That's simple enough. But how do I get to the hobbies inside of the array? I've tried doing:
user.hobby.indoor.type = req.body.type
But this doesn't work; it just gives me an error. Any help would be appreciated.
The following code will help you access your key properly. As hobby is an array, you need to provide an index for fetching its objects. Dot notation works with objects
user.hobby[0].indoor.type
Js Fiddle: https://jsfiddle.net/x18nyd2e/
So I did end up finding the answer to my problem. Here is an example of what to do:
var user = new User();
user.username = req.body.username;
user.hobby = {{
indoor: {
type: req.body.type,
description: req.body.description
}
}];
And that's how you can get to a property inside of an array.

MongoDB: index on collection names themselves

Say I have a simple user schema:
var userSchema = new mongoose.Schema({
username: String,
password: String,
notifications: [{
message: String,
dateCreated: Date,
}]
});
module.exports = mongoose.model('user',userSchema);
but what if we have a lot of users and we break apart the model, making notifications it's own collection like so:
var userSchema = new mongoose.Schema({
username: String,
password: String,
});
var notifsSchema = new mongoose.Schema({
message: String,
dateCreated: Date,
});
module.exports = function getModel(userId){
return mongoose.model('notifs_' + userId, notifsSchema)
}
so my question is: if we make notifications collections by user, so we have 200 users, therefore 200 notifications collections - is MongoDB smart enough to be able to index by collection name somehow? So if we have 100,000 users MongoDB can fins the notifications collection called 'notifs_394939329443'?

Resources