What is the proper way of mongoose populate? - javascript

Hello im new to nodejs and mongoose, i need help in mongoose populate, please help me to understand. Thanks in Advance!
here is my schema's
PropertySchema.js
const mongoose = require('mongoose')
const { Schema } = mongoose
require('./MemberSchema')
const propertySchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
pname: String,
ptype: String,
price: Number,
owner: { type: mongoose.Schema.Types.ObjectId, ref: 'Members' }
})
const Props = mongoose.model('Property', propertySchema)
module.exports = Property
MemberSchema.js
const mongoose = require('mongoose')
const { Schema } = mongoose
require('./PropertySchema')
const memberSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
fname: String,
lname: String,
dob: Number,
email: String,
address: String,
phone: Number,
memtype: String,
username: {type: String, required: true},
password: {type: String, required:true},
properties: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Property' }]
})
const Members = mongoose.model('Members', memberSchema)
module.exports = Members
addPropertyRoutes.js
router.post('/add', isAuthenticated, (req, res, next) => {
const props = new Property({
_id: new mongoose.Types.ObjectId(),
pname: req.body.pname,
ptype: req.body.ptype,
price: req.body.price,
owner: new mongoose.Types.ObjectId()
})
props.save( (err, props) => {
if (err) {
console.log('Unable to register your data: ' + err)
throw err
}
console.log('Property Added Successful!')
res.redirect('/property/add')
})
})
Im using mongoose 3.6 and expressjs.
When i check my Robo 3t after adding properties it shows like this check this screenshot:

In your, property schema you have to store ownerId, not to generate new ObjectId.
The proper way to do Populate in mongoose, you can find it here.

i think the solution is this:
change your addPropertyRoutes into this :)
router.post('/add', isAuthenticated, (req, res, next) => {
const member = req.user
Members.findOne({})
const props = new Property({
pname: req.body.pname,
ptype: req.body.ptype,
price: req.body.price,
owner: member._id
})
props.save( (err, props) => {
if (err) {
console.log('Unable to register your data: ' + err)
throw err
}
console.log('Registration Successful!')
res.redirect('/property/add')
})
})
Your Welcome from noobs

Related

Method expression is not of Function type (mongoose Model)

i came across this error today and did not find a fix for it.
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
name: {type:String, required:false},
birthday: {type:String, required:false},
email: {type:String, required:false},
hobbies: {type:String, required:false},
picture: {type:String, required:false},
});
const User = mongoose.model("User",userSchema);
module.exports = User;
If you hover over Schema it will show the error : "Method expression is not of Function type"
I later use this Schema here:
const User = require("../models/user");
exports.createUser = (req, res, next) => {
const url = req.protocol + "://" + req.get("host");
const user = new User({
name: req.body.name,
birthday: req.body.birthday,
email: req.body.email,
hobbies: req.body.hobbies,
picture: req.body.picture
});
console.log(user);
user
.save()
.then((createdUser) => {
console.log(createdUser);
res.status(201).json({
message: "User added successfully",
});
})
.catch((error) => {
res.status(500).json({
message: "Creating user failed!",
});
});
};
The console log of user is the following:
{
name: 'Chris',
birthday: 'test',
email: 'test',
hobbies: 'test',
picture: 'test',
_id: new ObjectId("61c0a908e340bcdec1011de5")
}
The _id should not contain new ObjectId and only the part in the brackets.
I hope you can find a fix for this or an idea on how it should be done.
According to the latest Mongoose docs, if you redo it like so:
import mongoose from 'mongoose';
const { Schema } = mongoose;
const userSchema = new Schema ({
...
});
That should fix it, so you're creating a new instance of a Schema object, rather than calling a Schema "method".

MongoDB Unable to push to array with findOneAndUpdate()

Been working on a project recently where users subscribe to a class... however I am having trouble with pushing the class to the array... here is my code
const userSchema = new mongoose.Schema({
email: String,
password: String,
secret: String,
classes: [String]
});
const userModel = mongoose.model("Class", userSchema)
app.post("/subscribe", function (req, res) {
const newClass = req.body.subClass;
const id = req.user.id
const ObjectId = mongoose.Types.ObjectId;
userModel.findOneAndUpdate(
{ _id: new ObjectId(id) },
{ $addToSet: { letters: [newClass] } },
{ upsert: false }
);
});
I skipped through the program for useful info so please comment if more code is needed... looking to finally finish this up!

populate method in mongoose (node js)

I m trying to use populate( ) in node js.
Well I m trying to access, objectId of one collection into another collection.
for eg., i have collections called Project and events,
where i have schema like this.
Project schema:
const projectSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
projectName: {
type: String,
required: true,
unique: true
},
dimensions: {
type: [],
required: false
},
events: {
[type: mongoose.Schema.Types.ObjectId],
ref: 'EnrichedEvent'
},
});
module.exports = mongoose.model('Project', projectSchema);
Events Schema:
const enrichedEventSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
projectId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Project',
required: true
},
name: {
type: String,
required: true
},
type: {
type: String,
enum: ["Enriched"],
required: true
},
source: {
type: String,
required: true
},
});
and the routing code for projects to :
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const Project = require("../models/project");
router.get("/", (req, res, next) => {
Project.find()
.populate('source', 'EnrichedEvents') //When i use this populate method, I m not able to GET any events on to browser..
.exec()
.then(docs => {
const response = {
count: docs.length,
projects: docs.map(doc => {
return {
projectName: doc.projectName,
dimensions: doc.dimensions,
events: doc.events,
_id: doc._id
};
})
};
res.status(200).json(response);
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
router.post("/", (req, res, next) => {
const project = new Project({
_id: new mongoose.Types.ObjectId(),
projectName: req.body.projectName,
events: req.body.events
});
project
.save()
.then(result => {
console.log(result);
res.status(201).json({
message: "Created project successfully",
createdProject: {
projectName: result.projectName,
_id: result._id,
events: result.events,
}
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
module.exports = router;
my problem is I can't auto populate the enriched eventsId in projects page.
for eg. Whenever i update events they should appear in projects page.but its not happening. In events page also i am not getting corresponding projectId. please point me in right direction.
Populate method takes FIELD_TO_POPULATE and FIELDS_TO_RETURN_FROM_POPULATED_DOC and you are passing it the reversed way. Also in your project schema you have used events for EnrichedEvent, so while populating use events not EnrichedEvent;
Try the following:
From:
.populate('source', 'EnrichedEvents')
TO:
.populate('events', 'EnrichedEvent')
Edit:
update your schema for EnrichedEvent:
events: [{
mongoose.Schema.Types.ObjectId,
ref: 'EnrichedEvent'
}]
It should work now.
I tried to use a similar .populate('...', '...') method but unsuccessfully. I would use
.populate('source').populate('EnrichedEvent')
or ('EnrichedEvents') depending on what you have defined in your schema.

Populate using mongoose doesn't return targeted ref collection

I have 2 collections, one is Credit, another one is User
credit
users
As you can see the credit's userId is the same with users's _id. How can I retrieve credit document when I retrieve that user? I've tried ref in schema but I don't get the data of credit, like so
exports.getUser = async function(req, res) {
const user = await User.findOne({_id: req.query.id})
.populate('credit')
.exec()
res.json(user)
}
CreditSchema
const CreditSchema = new Schema({
userId: Schema.Types.ObjectId,
credit: {
type: Number,
default: 0
},
log: [String]
})
UserSchema
const UserSchema = new Schema({
fullName: {
type: String
},
// etc.....
credit: {
type: Schema.Types.ObjectId,
ref: 'Credit'
}
})

content is missing from HTTP Get and Post requests in Express/Mongoose project

I have the following files. I have a recipe.js file which outlines the Mongoose Schema for a recipe and the comments for a recipe. The code for it goes as follows:
const express = require('express');
const mongoose = require('mongoose');
const User = require('../models/user');
let Schema = mongoose.Schema;
let commentSchema = Schema({
rating: {
type: Number,
// required: true,
min: 1,
max: 5,
},
recipeItem: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Recipe'
},
comment: {
type: String,
// required: true
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
likedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
favouredBy: {
type: mongoose.Schema.Types.ObjectId
}
});
let Comment = mongoose.model('Comment', commentSchema);
let recipeSchema = Schema({
name: {
type: String,
required: true
},
description: {
type: String,
},
steps: {
type: String,
required: true,
},
ingredients: {
type: Array,
required: true
},
comments: [commentSchema],
category: {
type: String,
required: true,
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
/// So I learnt that by defining the string as "Recipe" in the model function, I will have to lower case it
/// and pluralize it when I use it with res.json and other such things (i.e. "Recipe" => recipes).
let Recipe = mongoose.model('Recipe', recipeSchema);
module.exports = Recipe;
module.exports = Comment;
/// refactor this so that these are in the router, not in the models file
/*
module.exports.getRecipeByName = (name, callback) => {
let nameQuery = {name: name};
Recipe.findOne(nameQuery, callback);
};
module.exports.getRecipesByCategory = (category, callback) => {
Recipe.find({'category': category});
};
*/
I also have a user.js file where I outline a a User model and the relation it has to the other models/schemas. The code in the file is as follows:
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const passportLocalMongoose = require('passport-local-mongoose');
const passport = require('passport');
let Schema = mongoose.Schema;
let User = Schema({
name: {
type: String
},
// The passport plugin already inputs username and password into our Schema
username: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true,
},
profilePic: {
type: String
},
email: {
type: String,
unique: true,
required: true
},
admin: {
type: Boolean,
defualt: false
},
usersRecipes: [{type: Schema.Types.ObjectId, ref:'Recipe'}],
userComments: [{type: Schema.Types.ObjectId, ref: 'Comment'}],
usersFavouriteRecipes: [{type: Schema.Types.ObjectId, ref: 'Recipe'}],
usersLikedRecipes: [{type: Schema.Types.ObjectId, ref: 'Recipe'}]
});
let options = ({missingPasswordError: "Incorrect password, try again"});
User.plugin(passportLocalMongoose, options);
module.exports = mongoose.model('User', User);
And here is recipeRouter.js, the file where I define all the HTTP requests and routes:
const express = require('express');
const passport = require('passport');
const Recipe = require('../models/recipe');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const verification = require('../verification');
const Comment = require('../models/recipe');
// I temporarily removed verification.checkIfUserExists to see if all this database stuff works
router = express.Router();
router.use(bodyParser.json());
router.get('/', (req, res) => {
res.json('Here are the recipes!')
});
router.get('/showrecipes', (req, res) => {
Recipe.find({}).populate('Comment').exec((err, recipes) => {
if (err) throw err;
res.json(recipes);
})
});
router.get("/showrecipes/:recipeId", (req, res) => {
let nameQuery = {_id: req.params.recipeId};
Recipe.findOne(nameQuery, (err, recipes) => {
if (err) throw err;
res.json(recipes);
})
//// Don't know if this is correct
.populate('comment.recipeItem');
});
router.get('/showrecipes/category/:categoryname', (req, res) => {
let nameQuery = {category: req.params.categoryname};
Recipe.find(nameQuery, (err, recipes) => {
if (err) throw err;
res.json(recipes);
});
});
router.post('/addrecipe', (req, res, next) => {
Recipe.create({
name: req.body.name,
description: req.body.description,
steps: req.body.steps,
ingredients: req.body.ingredients,
category: req.body.category
}, (err, recipes) => {
if (err) throw err;
res.json(recipes);
});
});
// See if this works
router.put("/showrecipes/:recipeId", (req, res) => {
let query = {_id: req.params.recipeId};
Recipe.findByIdAndUpdate(query, {
$set: req.body
}, {
new: true
}, (err, recipe) => {
if (err) throw err;
res.json(recipe)
})
});
router.delete("/showrecipes/:recipeId", (req, res) => {
let query = {_id: req.params.recipeId};
Recipe.findByIdAndRemove(query, (err, recipe) => {
if (err) throw err;
res.send('Recipe was succesfully deleted');
})
});
router.get("/showrecipes/:recipeId", (req, res) => {
let nameQuery = {_id: req.params.recipeId};
Recipe.findOne(nameQuery, (err, recipes) => {
if (err) throw err;
res.json(recipes);
})
.populate('comments')
.exec((err) => {
if (err) throw err;
})
});
router.post("/showrecipes:/:recipeId/addcomment", (req, res, next) => {
Comment.create({
rating: req.body.rating,
comment: req.body.comment,
postedBy: postedBy,
date: Date.now(),
recipeItem: recipeId
})
});
router.get('/showrecipes/byuser/:username', (req, res) => {
let query = {postedBy: req.params.username};
Recipe.find(query, (err, recipes) => {
if (err) throw err;
res.json(recipes)
})
});
module.exports = router;
Now, at some point I was able to create recipes and store them in my database without a problem. But now this weird thing happens.
Here, I make my post request as you can see in the screenshot below:
But for some strange reason, everytime I make a get request, none of the key/value pairs I specified in my json body request are there. Each recipe object now only as the _id in it.
Can anyone help me? This just seems so weird.
Looks like you're simply missing the application/json Content-Type header.
In Postman, just set the header, as shown in this gif.

Categories