Mongoose populate not working for nested object - node.js

Client.js
const mongoose = require("mongoose");
var Schema = mongoose.Schema;
const clientSchema = new mongoose.Schema(
{
name: { type: String, required: true, default: "" },
}, {
timestamps: true
}
);
module.exports = mongoose.model("Client", clientSchema);
User.js
const mongoose = require("mongoose");
var Schema = mongoose.Schema;
const userSchema = new mongoose.Schema({
name: { type: String, required: true, default: "" },
clients: [{
client: {
type: Schema.Types.ObjectId,
ref: "Client",
default: null
},
user_group: {
type: Number
default: null
}
}]
}, { timestamps: true });
module.exports = mongoose.model("User", userSchema);
auth.js (Where trying to populate Clients)
const express = require("express");
const router = express.Router();
const User = require("../models/User");
const Client = require("../models/Client");
router.post("/users", (req, res) => {
let params = req.body;
let total_client = [];
User.findOne({
email: params.email
})
.populate({
path: "clients.client",
model: Client
})
.exec((err, user) => {
console.log(user);
res.send(user);
});
});
module.exports = router;
Please check the above code. I have given code examples of my two models user.js and client.js. In user schema, I have referenced client inside an array object. While querying user, the client is not population. Please help me to get this thing done. Thanks in advance.

The following expects you to provide a name in the json body of your post request (your example uses email which does not exist in the user model). Also, your model is already defining the ref: Client and so you can simplify your request to just include the path clients.client.
router.post("/users", async (req, res) => {
const { name } = req.body;
const user = await User.findOne({ name: name }).populate('clients.client').exec();
res.send(user);
});

Solved this problem just adding an extra parameter in module export of client.js file
module.exports = mongoose.model("Client", clientSchema, "client");

Related

Data is not stored in mongoDB database - node.js

I write node.js code and try to insert data into a mongodb database by Postman (post) but the data is not saved, only _id and _v are inserted into the documents ,that are entered automatically. I think the problem is in the body-parser, it is deprecated, but I tried a few options and it remained deprecated. (I'm not sure the problem with bodyparser).The data were inserteded via Postman(post). This is the relevant node.js code:
const express = require ('express');
const mongoose = require ('mongoose');
const router = require ('./routes/api');
const bodyParser = require("body-parser");
const dotenv = require('dotenv');
dotenv.config();
const app = express();
.
.
.
app.use(bodyParser.json());//this bodyParser is deprecated
app.use('/',router);
model:
const mongoose = require ('mongoose');
const userSchema = mongoose.Schema({
name:{
type:String,
require
},
password:{
type:String,
minlength:8,
require
}
})
module.exports = mongoose.model('User', userSchema);
controller:
const User = require ('../models/User');
const newUser = async (req,res)=>{
let user1 = new User(
req.body);
console.log(`${user1} added`);
try{
await user1.save();
res.status(200).json({newUser:user1});
}
catch(error){
res.send(`cant save new user: ${error.message}`)
}
}
module.exports = { newUser }
This is what I wrote in Postman:
{
"name":"james",
"password":"12345678"
}
and this is the response:
{
"newUser": {
"_id": "60a68f815019f31cfc098572",
"__v": 0
}
}
I would be very happy to get help !!
Please make the following changes to get the desired result.
// In place of app.use(bodyParser.json()), use
app.use(express.json())
// Controller
const userSchema = require("../models/User");
const newUser = async (req, res) => {
let user1 = new userSchema({
name: req.body.name,
password: req.body.password,
});
console.log(`${user1} added`);
try {
await user1.save().then(() => res.status(201).json({ newUser: user1 }));
} catch (error) {
res.send(`cant save new user: ${error.message}`);
}
};
module.exports = { newUser };
Also, inside the user schema, please change require to required: true.
// Model
const userSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
password:{
type: String,
minLength:8,
required: true
}
})
Modify your model.js file. It will check if anything is missing in req.body
const mongoose = require ('mongoose');
const userSchema = mongoose.Schema({
name:{
type:String,
required: true
},
password:{
type:String,
minlength:8,
required: true
}
})
module.exports = mongoose.model('User', userSchema);

(node: 5088) UnhandledPromiseRejectionWarning: ValidationError: Dev validation failed: name: Path `name` is required

Server.js
const express = require('express'); const mongoose =
require('mongoose');
const routes = require('./routes');
const server = express();
mongoose.connect("mongodb+srv://izaac:izaac#cluster0-hzrrk.mongodb.net/omnistack8?retryWrites=true&w=majority",
{ useNewUrlParser: true });
server.use(express.json()); server.use(routes);
server.listen(3333);
routes.js
const express = require('express'); const DevController =
require('./controllers/DevController');
const routes = express.Router();
routes.post('/devs', DevController.store);
module.exports = routes;
Dev.js
const { Schema, model } = require('mongoose');
const DevSchema = new Schema({ name: { type: String, required:
true, }, user: { type: String, required: true, }, bio:
String, avatar: { type: String, required: true, }, }, {
timestamps: true, });
module.exports = model('Dev', DevSchema);
DevController.js
const axios = require('axios');
const Dev = require('../models/Dev');
module.exports = {
async store(req, res) {
const { username } = req.body;
const userExists = await Dev.findOne({ user: username });
if (userExists) {
return res.json(userExists);
}
const response = await axios.get(`https://api.github.com/users/${username}`);
const { name, bio, avatar_url: avatar } = response.data;
const dev = await Dev.create({
name,
user: username,
bio,
avatar
});
return res.json(dev);
}
};
enter image description here
The 'name' field is required, but the response to your request has no 'name'.
In your schema design, the key name is required, So you need to log what data will be pass in Dev.create().

I can't handle populate in mongoose

I think it's not populating categories couse when i try log 'category' in console i get
"ReferenceError: category is not defined". For me it is like in docs but as we see it's not. Is anyone can tell me what is wrong??
//model/Category.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const CatSchema = new Schema({
title: {
type: String,
required: true
},
body: {
type: String,
required: true
}
});
mongoose.model("categories", CatSchema, "categories");
model/Story.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const StorySchema = new Schema({
title: {
type: String,
required: true
},
body: {
type: String,
required: true
},
category: {
type: Schema.Types.ObjectId,
ref: "categories"
}
});
mongoose.model("stories", StorySchema, "stories");
routes/stories.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Category = mongoose.model('categories');
const Story = mongoose.model('stories');
router.get('/add', (req, res) => {
Story.find()
.populate('category', 'title')
.then(stories => {
res.render('stories/add', {
stories: stories
});
});
});
Query.prototype.populate() returns a Query object on which you need to run .exec(), try this:
Story.find({})
.populate('category', 'title')
.exec()
.then(stories => {
res.render('stories/add', {
stories: stories
});
});
It was problem with that how I want to use it. Code is working

Mongoose plugin changes in pre 'save' and pre 'findOneAndUpdate' hooks do not get persisted

I have a node-express application that connects to MongoDB using the Mongoose library.
But I'm having problems getting my custom Mongoose plugins to bring changes to the documents before they are saved to the database.
Here is how I define my plugin:
const requestContext = require('request-context');
module.exports = (schema, options) => {
schema.pre('save', next => {
const author = requestContext.get('request').author;
this._createdBy = author.sub;
this._owner = author.sub;
this._groupOwner = author.group;
next();
});
schema.pre('findOneAndUpdate', next => {
const author = requestContext.get('request').author;
this._lastEditAt = Date.now();
this._lastEditBy = author.sub;
next();
});
}
Then I add it to the schema like this:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const trace = require('../plugins/trace');
const PostSchema = new Schema({
title: String,
Text: String,
category: String,
_createdAt: {
type: Date,
default: Date.now
},
_lastEditAt: Date,
_createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
_lastEditBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
_owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},_groupOwner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
}
});
PostSchema.plugin(trace);
exports.schema = PostSchema;
exports.model = mongoose.model('Post', PostSchema);
In my Express controller:
const router = require('express').Router();
const Post = require('../model/post').model;
router.post('/', (req, res) => {
const post = new Post(req.body);
post.save()
.then(() => res.json(post))
.catch(err => res.status(400).json(err));
});
router.put('/', (req, res) => {
Post.findByIdAndUpdate(req.body._id, req.body, {new: true})
.then(post => res.json(post))
.catch(err => res.status(400).json(err));
});
The pre hooks defined by the plugin are triggered but the changes they bring are never persisted to the database. Is this a bug in Mongoose plugin system.
I have tried with Mongoose#4.13.9 and Mongoose#5.3.3 but none works.
I was struggling with this issue during all the week-end.
Luckily I have found the origin of the problem.
First: I was using arrow functions for my hook methods, which changes the context of the this keyword.
So I had to define my hook functions using the old es5 function syntax as follows:
const requestContext = require('request-context');
module.exports = (schema, options) => {
schema.pre('save', function(next) {
const author = requestContext.get('request').author;
this._createdBy = author.sub;
this._owner = author.sub;
this._groupOwner = author.group;
next();
});
}

User.findByID is not a function

I am having an issue with node + express routing. I have a routing schema by default provided in the IDE webstorms. I am not sure if I configured everything well, because I am having this error.
I can do a GET /users and POST /users properly with correct results on postman.
routes/users.js
const express = require('express');
const router = express.Router();
const _ = require('lodash');
const {ObjectID} = require('mongodb');
const {mongoose} = require('../db/mongoose')
const {User} = require('../db/models/users')
const {Project} = require('../db/models/projects')
const {Dialog} = require('../db/models/dialogs')
(...)
router.get('/users/:userid', (req, res) => {
var id = req.params.userid.toString();
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
User.findByID(id).then((user) => {
if (!user) {
return res.status(404).send();
}
res.send({user});
}).catch(() => {
res.status(404).send();
});
});
models/users.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema
// todo refactor userschema with proper validators (view udemy course)
const UserSchema = new Schema({
email: {type: String, required: true},
password: {type: String, required: true},
name: {type: String},
company: {type: String},
phone: {type: String},
projects: [{type: Schema.Types.ObjectId, ref: 'Project'}]
});
const User = mongoose.model('User', UserSchema);
module.exports = {User}
Mikey is right. Mongoose model function is findById() not findByID() - http://mongoosejs.com/docs/api.html#model_Model.findById

Resources