Nested schema in Mongoose - node.js

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);

Related

Mongoose populate returns empty array with a simple,non-nested population

I am trying to populate a model but I am getting a empty array in return. I went throught every stack overflow answer but nothing solved my issue.
Here's my main schema:
const companySchema = new Schema({
name:{type:String,required:true},
img:{data: Buffer,contentType: String},
users:[{
name:String,
email:String,
allottedWarehouse:String,
}],
brands:[{type:Schema.Types.ObjectId,ref:'Brand'}],
warehouses:{type:Array},
shops:{type:Array}
})
Here's how I am trying to populate
exports.getCompanyDetails = function(req,res){
Company.findById(req.params.id)
.populate('brands')
.exec(function(err,selectedCompany){
if(err){
res.json('Something went wrong!')
}
console.log(selectedCompany.brands)
res.json(selectedCompany);
})
}
But in database it's just empty brands array,no id reference at all.
When I return it in res.json,it's empty too.
Here's my simple brand schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const BrandSchema = new Schema(
{
name: {type: String, required: true},
packSize:{type: Number, required: true},
})
module.exports = mongoose.model('Brand',BrandSchema);
I so badly need your help on this. Please look at it guys!Tell me where I am going wrong.

How to add an objectID to recursively embedded subdocuments

I have a variation on the question asked and solved by #Guilherme here but my recursive embedded documents are within another schema like this;
var mongoose = require('mongoose');
var CollectPointSchema = new mongoose.Schema({
name: {type: String},
collectPoints: [ this ]
});
var GroupSchema = new mongoose.Schema({
label: {type: String},
points: [CollectionPointSchema]
});
const Group = mongoose.model("Group", GroupSchema);
I'd like to modify the solution that Guilherme proposed here but not sure how to go about it.
The main problem was that the child folders were not being populated with the name: field. I think because that field is not in the top level of the schema. So as a work-around I have added the name: field to the parent schema like this;
var GroupSchema = new mongoose.Schema({
label: {type: String},
name: {type: String},
points: [CollectionPointSchema]
});
and I also needed to change the order of Guilherme's solution from this;
var FolderModel = mongoose.model('folders', FolderSchema);
FolderSchema.pre('save', function(next) {
if (this.isNew) {
recursive_reference(FolderModel, this, "folders")
}
next();
});
to this;
FolderSchema.pre('save', function(next) {
if (this.isNew) {
recursive_reference(FolderModel, this, "folders")
}
next();
});
var FolderModel = mongoose.model('folders', FolderSchema);
The result is that I have an unused field at the parent level, but it works.

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-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);

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.

Resources