EDIT added mongoose.model.
I'm pretty new to mongodb and mongoose. I'm not able to populate books to authors in mongoose.
Can anyone help me with that? Here is my code. I removed unnecessary fields
const authorSchema = mongoose.Schema({
_id:{
type: String,
required: true,
unique: true,
trim: true
},
name: {
type: String,
required: true,
trim: true
},
books: [{
type: String,
ref: "Book"
}]
}, {_id:false})
const Author = mongoose.model('Author', authorSchema)
module.exports = {Author}
And my books schema looks as following
const bookSchema = mongoose.Schema({
_id:{
type:String,
required:true,
unique:true,
trim: true
},
name: {
type: String,
required: true,
trim: true,
unique: true
},
description:{
type: String,
trim: true,
default: 'No description specified'
},
datePublished: {
type: Date,
trim: true,
default: '01/01/2001'
},
author:{
type: String,
ref: 'Author',
required: true
}
}, {_id:false})
const Book = mongoose.model('Book', bookSchema)
module.exports = {Book}
Here is the route to populate them together
AuthorRouter.get('/authors/:id', async(req, res)=>{
const authorID = req.params.id
try {
const author = await Author.findById(authorID)
try {
const populated = await author.populate({path: 'books.book', select: 'name description -_id'})
console.log(populated);
res.status(201).send(populated)
} catch (e) {
res.status(401).send(`${e}\n Unable to populate categories`)
}
} catch (error) {
res.status(401).send('Unable to find author')
}
})
Output is following with empty books array:
{
"_id": "123",
"name": "testuser",
"books": [],
"__v": 0
}
Populating an arrays of refs works the same way as a single ref. Just call the populate method on the query and an array of documents will be returned in place of the original _id's.
In your case that would be:
const populated = await author.populate({path: 'books', select: 'name description -_id'});
Hey i have modify your code , try to use this one
This is your author schema file
const Schema = mongoose.Schema;
const authorSchema = mongoose.Schema({
_id:{
type: String,
required: true,
unique: true,
trim: true
},
name: {
type: String,
required: true,
trim: true
},
books: [{
type: Schema.Types.ObjectId,
ref: "bookSchema"
}]
}, {_id:false})
const Author = mongoose.model('Author', authorSchema)
module.exports = {Author}
And this is your route
AuthorRouter.get('/authors/:id', async(req, res)=>{
const authorID = req.params.id
try {
const author = await Author.findById(authorID)
try {
const populated = await author.find().populate('books');
console.log(populated);
res.status(201).send(populated)
} catch (e) {
res.status(401).send(`${e}\n Unable to populate categories`)
}
} catch (error) {
res.status(401).send('Unable to find author')
}
})
Related
I want to store or push whole reference document not a single reference id in Mongoose using Node.js.
Here user api details schema:
const {Schema} = require("mongoose");
const mongoose = require("mongoose");
const apiDetailSchema = new Schema({
endpoint:
{
type: String,
required: true,
trim: true
},
method:
{
type: String,
required: true,
trim: true,
},
secret:
{
type: String,
required: true,
trim: true
},
timeout:
{
type: Number,
required: true,
},
microservice:
{
type: String,
required: true,
},
status:
{
type: Number,
required: true,
},
user_type_id:
{
type: Schema.Types.ObjectId,
ref: 'UserType',
required: true
}
});
module.exports = apiDetailSchema;
Permissoin Schema
const {Schema} = require("mongoose");
const mongoose = require("mongoose");
const permission = new Schema({
role:
{
type: Schema.Types.ObjectId,
ref: 'Role'
},
Here I want to store whole api details document not single id
api_details:
[
{
type: Schema.Types.ObjectId,
ref: 'ApiDetail'
}
],
group:
{
type: String,
default: 0,
trim: true
},
status:
{
type: Number,
default: 0,
trim: true
}
});
module.exports = permission;
And here I push the ids like this:
async createPermission(req, res)
{
const permission = new Permission({
"role": req.body.role,
"group": req.body.group,
"status": req.body.status
});
const newPermissoin = await permission.save();
if(newPermissoin) {
const updatePermission = await Permission.findByIdAndUpdate(
newPermissoin._id,
{ $push: { "api_details": req.body.api_details_id } },
{ new: true, useFindAndModify: false }
);
return res.json( Response.success({message:
"Permission created successfully!", data: updatePermission}) );
}
}
How do I store the whole documents of api details in array form but here only reference of ids are stored.
i am trying to have my post's author's name in frontend. so i want to find the post according to it's user Id. but in model schema i used obejct Id of user in post Schema.
Here is my userSchema:
const mongoose = require('mongoose');
// user schema
const userSchema = new mongoose.Schema(
{
email: {
type: String,
trim: true,
required: true,
unique: true,
lowercase: true
},
name: {
type: String,
trim: true,
},
password: {
type: String,
required: true
},
salt: String,
bio: {
type: String,
trim: true
},
role: {
type: String,
default: 'subscriber'
},
resetPasswordToken: String,
resetPasswordExpire: Date,
},
{
timestamps: true
}
);
module.exports = mongoose.model('User', userSchema);
here is my postSchema model:
const mongoose = require("mongoose");
const PostSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
content: {
type: String,
required: true,
},
comments: [{
text: String,
created: { type: Date, default: Date.now },
postedBy: { type: mongoose.Schema.ObjectId, ref: 'User'}
}],
created: {
type: Date,
default: Date.now
},
creator: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
},
{
timestamps: true,
},
);
const Post = mongoose.model("Post", PostSchema);
module.exports = Post;
and here is my router for post lists by a specific user id:
exports.postByUser=async(req,res)=>{
try
{
const userID=async()=>{
await User.findById({ _id:req.params.id})
.then(posts=>{
res.status(200).json(posts.name)
})
}
await Post.find({creator: req.params.id})
.then(posts=>{
res.status(200).json(posts)
})
}catch(error){
res.status(500).send({error: error.message});
};
}
router.route('/post/mypost/:id').get(requireSignin,postByUser);
my target is to get a post list where every post's creator would have the user name. how can i achieve that in nodejs?
i have solved this way:
exports.postByUser=async(req,res)=>{
try
{
await Post.find({creator: req.params.id})
.populate({path:'creator', select:'name -_id'})
.then(post=>{
res.status(200).json(post)
})
}catch(error){
res.status(500).send({error: error.message});
};
}
and it worked
i have 2 schemas
const schema = mongoose.Schema(
{
id_film: {
type: Number,
unique: true,
require: true,
trim: true,
},
recommendation: [{
type: Number,
ref: 'Films'
}]
}, { timestamps: true }, { _id: false }
);
export const Recommendation = mongoose.model("Recommendations", schema);
const schema = mongoose.Schema(
{
name:{
type: String,
}
id: {
type: Number,
ref: 'Recommendations'
},
}
export const Films = mongoose.model("Films", schema);
the recommendation contains a list id of model Films, and I want to show all id film
i try it
Recommendation.findOne({ id_film: req.params.id }).populate('recommendation').exec(function (err, film) {
if (err) return handleError(err);
res.json(film);
});
but it's not working, it just shows the list id not id and name
I am developing a sample API for restaurants in which I want retrieve data of restaurants by entering the Restaurant's name. Controller, Model & Router has been set but if I load it into Postman data doesn't appear. Please share some ideas.
Controller: (restaurant.js)
const restaurants = require('../Models/restaurantData');
exports.getRestaurantName = (req, res) => {
const Name = req.params.name;
restaurants.find({
name: Name
}).then(result => {
res.status(200).json({
message: "Restaurant Data",
restaurants: result[0]
});
}).catch(error => {
res.status(500).json({
message: error
});
});
}
Model: (restaurantData.js)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const restaurantSchema = new Schema({
_id: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
city_name:{
type: String,
required: true
},
city_id: {
type: String,
required: true
},
location_id: {
type: Number,
required: true
},
area: {
type: Number,
required: true
},
locality:{
type: String,
required: true
},
thumb: {
type: String,
required: true
},
cost:{
type: Number,
required: true
},
address:{
type: String,
required: true
},
mealtype:{
type: Number,
required: true
},
name:{
type: String,
required: true
},
cuisine:{
type: Number,
required: true
},
type:{
type: Array,
required: true
},
Cuisine:{
type: Array,
required: true
}
});
module.exports = mongoose.model('restaurantData', restaurantSchema, 'restaurantData');
Router:
const express = require('express');
const restaurantController = require('../Controllers/restaurant');
const router = express.Router();
router.get('/restaurantData/:name',restaurantController.getRestaurantName);
module.exports = router;
had you add network access if yes then use Model.create(req.body(err,data)={ res.send(data); })
Change the following and I hope it will work.
In Restaurant Model, remove this:
module.exports = mongoose.model( "restaurantData", restaurantSchema, "restaurantData");
And add this:
const Restaurant = mongoose.model("restaurantData", restaurantSchema);
module.exports = { Restaurant };
In your Restaurant controller, change the import script into:
const { Restaurant } = require("../Models/restaurantData");
And Method will be:
Restaurant.find({
name: Name,
})
Change the variable and file names according to your need.
I think the problem might be while creating the model out of the schema
module.exports = mongoose.model('restrauntData', restaurantSchema);
use the above instead of
module.exports = mongoose.model( "restaurantData", restaurantSchema, "restaurantData");
then it should work fine.
Im relatively new to MongoDB and Mongoose. Im much used to MySQL so in used to inner joining tables on calls. Ive read a lot that you can link two Mongoose Schemas to achieve the same outcome. How would like like the two schemas together to when I make a call to get a chore by id it'll return the chore and then for the assignedTo & createdBy have the user scheme data for the said userId?
Chore Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ChoreSchema = new Schema({
title: {
type: String,
required: true
},
desc: {
type: String,
required: true
},
time: {
type: Number,
required: true
},
reaccurance: {
type: [{
type: String,
enum: ['Daily', 'Weekly', 'Bi-Weekly', 'Monthly']
}]
},
reward: {
type: Number,
required: true
},
retryDeduction: {
type: Number,
required: false
},
createdDate: {
type: Date,
default: Date.now
},
createdBy: {
type: String,
required: true
},
dueDate: {
type: Date,
required: true
},
status: {
type: [{
type: String,
enum: ['new', 'pending', 'rejected', 'completed', 'pastDue']
}],
default: ['new']
},
retryCount: {
type: Number,
default: 0,
required: false
},
rejectedReason: {
type: String,
required: false
},
familyId: {
type: String,
required: true
},
assignedTo: {
type: String,
required: false,
default: ""
}
});
let Chores = module.exports = mongoose.model('Chores', ChoreSchema);
module.exports.get = function (callback, limit) {
Chores.find(callback).limit(limit);
};
User Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
role: {
type: [{
type: String,
enum: ['Adult', 'Child']
}]
},
birthday: {
type: String,
required: false
},
familyId: {
type: String,
required: true
},
balance: {
type: Number,
required: true,
default: 0.00
}
});
let Users = module.exports = mongoose.model('Users', UserSchema);
module.exports.get = function (callback, limit) {
Users.find(callback).limit(limit);
};
Im trying to link ChoreSchema.createdBy & ChoreScheme.assignedTo by UserSchema._id
How I make the call in Node.js:
exports.index = function(req, res) {
Chore.get(function(err, chore) {
if (err)
res.send(err);
res.json({
message: 'Chore List',
data: chore
});
});
};
Mongoose has a more powerful alternative called populate(),
which lets you reference documents in other collections.
https://mongoosejs.com/docs/populate.html
Here is how you can link ChoreSchema.createdBy and ChoreScheme.assignedTo by UserSchema._id
var mongoose = require('mongoose');
const { Schema, Types } = mongoose;
var UserSchema = new Schema({
firstName: { type: String, required: true },
...
})
var ChoreSchema = new Schema({
title: { type: String, required: true },
...
//The ref option is what tells Mongoose which model to use during population
assignedTo: { type: Types.ObjectId, ref: 'Users' },
createdBy: { type: Types.ObjectId, ref: 'Users' },
})
let Chores = mongoose.model('Chores', ChoreSchema);
let Users = mongoose.model('Users', UserSchema);
Then in your express route handler you can populate assignedTo & createdBy like this
router.get('/chores/:id', function (req, res) {
const choreId = req.params.id;
Chores.find({ _id: choreId })
.populate('createdBy') // populate createdBy
.populate('assignedTo') // populate assignedTo
.exec(function (err, chore) {
if(err) {
return res.send(err)
}
res.json({ message: 'Chore List', data: chore });
});
})