MongoDB: index on collection names themselves - node.js

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'?

Related

Combining Mongo Schemas

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

mongoose-schema - are both children array + parent doc's ID necessary?

I'm using a couple of one-to-many models and was wondering what the advantage of having both an array of "children" ObjectID()s and a "parent" model's ObjectID() in the child is. For example:
// a client will have a new card every ten visits
var ClientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [] // ObjectID()s, <--- is this necessary?
});
var CardSchema = new Schema({
client: ObjectID(), // <--- or is this enough?
visits: []
});
I think the client: ObjectID() should do the trick in most cases, specially with the Population options Mongoose offers.
It suffices to store the reference ObjectId in one of the documents.
As you can read in the documentation or in this answer, the reference field needs a type and a ref. The name of field is arbitrary. Once you have done this and registered your models, you can use the models to populate your queries.
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String
});
var cardSchema = new Schema({
client: {
type: Schema.Types.ObjectId,
ref: 'client'
}
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);
Yet, it could be helpful to store an array of ObjectId's. However, this also creates a huge window for mistakes. A mismatch of foreign key and primary key, in SQL dialect. You can always do a count query if you need to count. I would say, do either the above or do this:
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [
{
type: Schema.Types.ObjectId,
ref: 'card'
}
]
});
var cardSchema = new Schema({
card_name: String
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);

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'}}
})

mongoose - storing an array of ids in mongoDB at storage time, but getting entire objects back at runtime?

I am trying to setup a mongoose model of what I want in my mongodb instance.
here is the code I have for a user type so far.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema(
{
username: String,
userType: int,
tagline: String,
friends: <Not sure what to do here>
}));
Essentially, I want to only store the ids of other users in here at insert time etc, but when I query to GET this user, I want to actually get the json that would have the various users I want to get back.
Mongoose provides a mechanism for referencing other collections and populating them. I'm making the assumption the _ids in friends are other Users so you can define your schema as
module.exports = mongoose.model('User', new Schema(
{
username: String,
userType: int,
tagline: String,
friends: [{type: ObjectId, ref: 'User'}]
}));
And then you can use the built in populate method in mongoose to retrieve the actual documents and not just the _ids
User
.findOne({ username: username })
.populate('friends')
.exec(function (err, user) {
if (err) return handleError(err);
console.log(user.friends);
});
I need to use Population. So you define your fields as ref:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User', new Schema({
username: String,
userType: int,
tagline: String,
friends:[{type: Schema.ObjectId, ref: 'User'}]
}));
And could fetch your friends as array of objects via .populate method:
User.findById(id)
.populate('friends')
.exec(function (err, user) {
if (err) throw err;
// user.friends is array of users
console.log(user.friends)
})

Nested schema in Mongoose

Thanks for your help and valuable time. As you suggested I have created the schema's as below. Now I want to get records based on customer name to calculate the hours spent by them on each category. Please help me out in this. Thanks in Advance.
/*var query = {'timesheets[0].categories[0].catname':"Admin"} // I want to get all the records or documents with category admin */
Timesheet = new Schema({
created: {type: Date, default: Date.now},
categories: [{
catname: String,
custname: String,
hours: Number
}]
});
User = new Schema({
name: { type: String, required: true },
email:String,
password:String,
type:String,
timesheets: [Timesheet]
});
//timesheets: [{type: mongoose.Schema.Types.ObjectId, ref: 'Timesheet'}
var User = mongoose.model("User",User);
var Timesheet = mongoose.model("Timesheet",Timesheet);
module.exports = function(app) {
var timedata = {
created: new Date('2014-06-05'),
categories:[{catname:"Admin",cusname:"Sony",hours:8}]
}
var user = new User({
name:"Nelson",
email:"nelson#gmail.com",
password:"welcome123",
type:"Solutions"
});
var timesheet = new Timesheet(timedata);
user.timesheets.push(timesheet);
user.save(function(err,user){
console.log(user.timesheets.timesheet);
})
//console.log('category name');
//console.log(user.timesheets[0].categories[0].catname)
var query = {'timesheets[0].categories[0].catname':"Admin"}
// I want to get
all the records or documents with category admin
User.find(query,function(err,catname){
console.log('catname')
console.log(catname)
})
To create a child schema you should first define it and then insert into your primary schema. Alternatively, if you anticipate a lot of timesheets it's probably preferable to reference an independent schema. In both cases it would make sense to attach these to a User schema:
var Timesheet = new Schema({
created: {type: Date, default: Date.now},
categories: [{
name: String,
custname: String,
hours: Number
}]
});
Using embedded documents:
var User = new Schema({
timesheets: [Timesheet]
});
Insert can then be done directly using:
// create new timesheet doc using your user doc
var timesheet = user.timesheets.create(myData);
user.timesheets.push(timesheet);
or simply:
user.timesheets.push(data);
Using referenced documents:
var User = new Schema({
timesheets: [{type: Schema.Types.ObjectID, ref: 'Timesheet'}]
});
insert with:
// push timesheet reference to your user doc
var timesheet = new Timesheet(data);
user.timesheets.push(timesheet._id);

Resources