My schema is as below
Sectionschema
var SectionSchema = new Schema({
name: String,
documents : {
type : [{
type: Schema.ObjectId,
ref: 'Document'
}]
}
}
}
DocumentSchema
var DocumentSchema = new Schema({
name: String,
extension: String,
access: String, //private,public
folderName : String,
bucketName : String,
desc: String
});
Api.js
exports.section = function(req, res, next, id) {
var fieldSelection = {
_id: 1,
name: 1,
documents : 1
};
var populateArray = [];
populateArray.push('documents');
Section.findOne({
_id: id
}, fieldSelection)
.populate(populateArray)
.exec(function(err, section) {
if (err) return next(err);
if (!section) return next(new Error('Failed to load Section ' + id));
// Found the section!! Set it in request context.
req.section = section;
next();
});
}
If I go this way, I have
the 'documents' object is []. However if I remove, "populateArray.push('documents');" then I get documents:['5adfsadf525sdfsdfsdfssdfsd'] -- some object Id (atleast)
Please let me know the way I need to populate.
Thanks.
Change your query to
Section.findOne({
_id: id
}, fieldSelection)
.populate('documents.type')
.exec(function(err, section) {
if (err) return next(err);
if (!section) return next(new Error('Failed to load Section ' + id));
// Found the section!! Set it in request context.
req.section = section;
next();
});
and this works. You need to give the path to populate.
If you just want "documents" in your schema pointing to Array of ObjectID which you will populate later. then you can use this.
var SectionSchema = new Schema({
name: String,
documents : [{
type: Schema.ObjectId,
ref: 'Document'
}]
});
And use the following to populate it
Section.findOne({
_id: id
}, fieldSelection)
.populate('documents')
.exec(function(err, section) {
if (err) return next(err);
if (!section) return next(new Error('Failed to load Section ' + id));
// Found the section!! Set it in request context.
req.section = section;
next();
});
Related
I'm building my first mean stack app. It's a review site that contains three models: User, Review, and Company.
When I make a review, I want the new review to be saved to the 'review' collection, and for that review to be connected by reference to the company being reviewed and the user who wrote the review. I also want the user to hold a reference to the review, and the company to hold a reference to all the reviews it has. Here are my models:
Review
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const reviewSchema = new Schema ({
companyName: String,
companyId: { type: Schema.Types.ObjectId, ref: 'Company'},
starRating: Number,
subject: String,
commentBody: String,
createdBy: { type: Schema.Types.ObjectId, ref: 'User'},
});
const Review = mongoose.model("Review", reviewSchema);
module.exports = Review;
Company
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const companySchema = new Schema ({
companyName: String,
about: String,
basedIn: String,
materialOrigins: [String],
productRange: [String],
category: String,
reviews: [ {type: Schema.Types.ObjectId, ref: 'Review'} ],
socialRating: Number,
environmentalRating: Number,
priceRange: Number
});
const Company = mongoose.model("Company", companySchema);
module.exports = Company;
User
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema ({
email: String,
firstName: String,
lastName: String,
password: String,
image: Object,
aboutText: String,
reviews: [ { type: Schema.Types.ObjectId, ref: "Review" } ]
// comments: { type: Schema.Types.ObjectId, ref: 'Comment' }
});
const User = mongoose.model("User", userSchema);
module.exports = User;
This is my current route, which currently saves the review to the collection and attaches the user. However, the user doesn't get the review.
route
router.post('/:category/:company', (req, res) => {
var subject = req.body.subject;
var commentBody = req.body.commentBody;
var starRating = req.body.starRating;
var userId = req.body.userId;
if(!subject || !commentBody || !starRating) {
res.status(400).json({ message: "Subject, comment body, and star rating are required." });
return;
}
var newReview = Review({
starRating,
subject,
commentBody,
userId
});
User.findById(userId, {
}, (err, user) => {
if (err) {
return res.send(err);
} else {
console.log("checking out user in route", user);
user.reviews.push(newReview);
user.save();
newReview.save((err, review) => {
if (err) {
return res.status(400).json({ message: err });
} else {
res.status(200).json({ message: 'Review saved', review });
}
});
}
});
I haven't tried adding the company in because I'm trying to do one thing at a time. I've been looking at 'populate', but all of the documentation seems to only use two models at once. Is it possible to do three at once? Or am I overcomplicating this?
Apologies if this is all overcomplicated. I'm fairly new to MongoDB and MEAN stack in general. Thanks for your help.
Ok, I did it, for any people landing on this page wondering the same thing in the future.
Here's my route:
router.post('/:category/:company', (req, res, next) => {
var companyName;
var companyId;
var subject = req.body.subject;
var commentBody = req.body.commentBody;
var starRating = req.body.starRating;
var createdBy = req.body.createdBy;
if(!subject || !commentBody || !starRating) {
res.status(400).json({ message: "Subject, comment body, and star rating are required." });
return;
}
var newReview = Review({
starRating,
subject,
commentBody,
createdBy
});
//I need the companyId and companyInfo for later use in my review save. I'm calling the company with the name I have from my params, and setting the id and name with the received data from Mongo.
Company.findOne({"companyName": req.params.company}, (err, company) => {
if (err) {
return res.status(400).json({ message: err });
} else {
this.companyName = company.companyName;
this.companyId = company.id;
}
});
newReview.save((err, review) => {
//Push the review id to the user
if (err) {
return res.status(400).json({ message: err });
} else { User.findByIdAndUpdate({_id: createdBy },{$push: {reviews: review.id} }, (err) => {
if (err) {
console.log("There was an error pushing review to user");
next(err);
//Push the review id to the company
} else { Company.findOneAndUpdate({ "companyName": req.params.company}, {$push: {reviews: review.id}}, (err, company) => {
if (err) {
console.log("There was an error pushing review to company");
next(err);
} else {
//Updates the review by setting companyId and companyName properties to review for Mongo
Review.update({_id: review.id}, {$set: {companyId: this.companyId, companyName: this.companyName}}, (err, changes) => {
if(err) {
return res.status(400).json({message : err});
} else {
console.log("updating review successfully with company info", changes);
}
});
console.log ("Review successfully saved");
res.json({
review: review,
});
}
});
}
});
}
});
});
If anyone has feedback on how this could be done better/more efficiently, let me know. Cheers.
I have 2 collections called User and Location. In User, there is a location _id and this is an Object. Id also references the location collection. My question is what did I do wrong? When I call getUser function I want to see user information and the user's location information. What I need to do ?
User Schema
module.exports = (function userSchema() {
var Mongoose = require('mongoose');
var userSchema = Mongoose.Schema({
name: {
type: String,
require: true
},
surname: {
type: String,
require: true
},
tel: {
type: String,
require: true
},
age: {
type: String,
require: true
},
mevki_id: {
type: String,
require: true
},
location_id: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'locations'
}]
});
var collectionName = 'users';
var User = Mongoose.model(collectionName, userSchema);
return User;
})();
User Controller
function userController() {
var User = require('../models/UserSchema');
this.createUser = function (req, res, next) {
var name = req.body.name;
var surname = req.body.surname;
var tel = req.body.tel;
var age = req.body.age;
var mevki_id = req.body.mevki_id;
var lok_id = req.body.lok_id;
User.create({
name: name,
surname: surname,
tel: tel,
age: age,
mevki_id: mevki_id,
lok_id: lok_id
}, function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'result': result,
'status': 'successfully saved'
});
}
});
};
this.getUser = function (req, res, next) {
User.find()
.populate('lok_id')
.exec(function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'USERS': result
});
}
});
};
return this;
};
module.exports = new UserController();
First, your schema is wrong:
var userSchema = new Mongoose.Schema({
// ...
location_id: { type: [Mongoose.Schema.Types.ObjectId], ref: 'locations' }
})
Second, in your schema the last field name is location_id while in your controller, you change it to lok_id.
So, fix this:
User.create({
// ...
location_id: lok_id
}
and this:
User
.find()
.populate('location_id')
UPDATE
In your json the last field name is location_id, therefore, fix this too:
this.createUser = function (req, res, next) {
// ...
var lok_id = req.body.location_id;
}
There is no another error but I want to know just one thing.How to use that give reference in User schema object _id it means location_id how to use when I add new User.
User Schema :
var userSchema = Mongoose.Schema({
name:{type: String,require:true},
surname: {type: String,require:true},
tel: {type: String,require:true},
age: {type: String,require:true},
mevki_id: {type: String,require:true},
location_id: { type: Mongoose.Schema.Types.ObjectId, ref: 'locations' }
});
Location schema:
var LocationSchema = Mongoose.Schema ({
il: {type: String, require:true},
ilce: {type:String, require:true}
});
UserController -- I add user here
this.createUser = function(req, res) {
var la=new Location({il:'istanbul',ilce:'camlica',location_id:la._id}).save(function (err) {
if (err) return handleError(err);
});
var user = new User({
name:'akif',surname:'demirezen',tel:'544525',age:'45',mevki_id:'2',
}).save(function (err) {
if (err) return handleError(err);
res.send(JSON.stringify(job));
});
}
There are several errors in your code. For example, the require property should be required.
Other problem is that you are setting the location_id value of la with a reference to la, that at that time has not been yet assigned a value.
Mongo will automatically create a field called _id: ObjectId on all your objects. Try this:
this.createUser = function(req, res) {
var la = new Location({
il:'istanbul',
ilce:'camlica',
}).save(function (err, location) {
if (err) return handleError(err);
var user = new User({
name:'akif',
surname:'demirezen',
tel:'544525',
age:'45',
mevki_id:'2',
location_id: location._id
}).save(function (err, user) {
if (err) return handleError(err);
// Warning: AFAIK job does not exist, should it be user?
res.send(JSON.stringify(job));
});
});
}
I have an existing document that contains a nested array of elements (I'm not exactly sure of the terminology here). I have no problem creating the document. The problem arises when I need to insert a new element into the existing document. The code below may clarify what I'm trying to do:
Controller:
var Post = require('./models/post');
app.post('/post/:id/comment', function(req, res) {
var updateData = {
comments.comment: req.body.comment
comments.name: req.body.name,
};
Post.update({_id: req.params.id},updateData, function(err,affected) {
console.log('affected rows %d', affected);
});
});
Model:
var mongoose = require('mongoose');
var postSchema = mongoose.Schema({
post : String,
name : String,
created : {
type: Date,
default: Date.now
},
comments : [{
comment : String,
name : String,
created : {
type: Date,
default: Date.now
}
}]
});
module.exports = mongoose.model('Posts', postSchema);
So, each post can contain multiple comments. I'm just not sure how to insert a new comment into an existing post.
Since comments is declared as array, try to use
Post.update({_id:yourid}, { $push : { comments: { comment: '', name: '' } } }, ...
You can convert the object returned from mongodb in to an js object, and push new comment into the comments array. See the following:
var postSchema = require('./postSchema'); // your postSchema model file
postSchema.findOne({name: 'name-of-the-post'}, function (err, doc) { //find the post base on post name or whatever criteria
if (err)
console.log(err);
else {
if (!doc) { //if not found, create new post and insert into db
var obj = new postSchema({
post: '...'
name: '...'
...
});
obj.save(function (err) {
if (err)
console.log(err);
});
} else {
// if found, convert the post into an object, delete the _id field, and add new comment to this post
var obj = doc.toObject();
delete obj._id;
obj.comments.push(req.body.comment); // push new comment to comments array
postSchema.update(
{
'_id': doc._id
}, obj, {upsert: true}, function (err) { // upsert: true
if (err)
console.log(err);
});
}
console.log('Done');
}
});
I have the following two schemas and models:
var Customer = new Schema({
name: String,
jobs: [{ type: Schema.Types.ObjectId, ref: 'Job' }]
});
var Job = new Schema({
title: String,
customer: { type: Schema.Types.ObjectId, ref: 'Customer' }
});
var CustomerModel = mongoose.model('Customer', Customer);
var JobModel = mongoose.model('Job', Job);
job documents have a reference to the customer document via _id, and the customer document also contains an array of all the jobs _id's.
When I delete a job I need to delete the corresponding _id from the Customer.jobs array.
Here is the route I have - the job gets deleted but I cannot remove it's id from the array
app.delete('/api/jobs/:jobId', function(req, res){
return JobModel.findById(req.params.jobId, function(err, job){
return job.remove(function(err){
if(!err){
CustomerModel.update({_id: job.customer._id}, {$pull : {'customer.jobs' : job.customer._id}}, function(err, numberAffected){
console.log(numberAffected);
if(!err){
return console.log('removed job id');
} else {
return console.log(err);
}
});
console.log('Job removed');
return res.send('');
} else{
console.log(err);
}
});
});
});
numberAffected is always 0 and 'removed job id' always get fired
You've got things backwards in your $pull. Try this instead:
CustomerModel.update({_id: job.customer}, {$pull : {jobs : job._id}}, ...