Building API for model that has referenced attribute - javascript

so my question is how can i display data of a model that has an attribute reference to another model? In this task i have Driver model that has attribute state which should reference another model called State that has a name attribute. I know hot to reference models in mongoose but i don't know how to build API for creating new Driver and displaying it.
Below is my Driver and State models
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let Driver = new Schema({
name: {
type: String
},
phone: {
type: String
},
email: {
type: String
},
deleted: {
type: Boolean
},
state: {
type: Schema.ObjectId,
Ref: 'State'
}
});
module.exports = mongoose.model('Driver', Driver);
This is model of State
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let State = new Schema({
name: {
type: String
}
});
module.exports = mongoose.model('State', State);
Currently my API are looking like this
driverRoutes.route('/').get(function(req, res){
Driver.find(function(err, drivers){
if(err){
console.log("Error");
} else {
res.json(drivers);
}
});
});
driverRoutes.route('/:id').get(function(req, res){
let id = req.params.id;
Driver.findById(id, function(err, temp){
res.json(temp);
});
});
driverRoutes.route('/add').post(function(req, res){
let temp = new Driver(req.body);
temp.save()
.then(temp =>{
console.log(temp.state);
res.status(200).json({'driver': 'driver added successfully'});
})
.catch(err => {
res.status(400).send('adding new driver failed');
});
});
Route with / is to display all Drivers in table.

Change your Driver model to look as below,
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let Driver = new Schema({
_id: {
type:Schema.Types.ObjectId
},
name: {
type: String
},
phone: {
type: String
},
email: {
type: String
},
deleted: {
type: Boolean
},
state: {
type: Schema.Types.ObjectId, //this is the change made
Ref: 'State'
}
});
module.exports = mongoose.model('Driver', Driver);
The second step is optional. That is, in your state model,
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let State = new Schema({
_id:{
type:Schema.Types.ObjectId //this is optional however
},
name: {
type: String
}
});
module.exports = mongoose.model('State', State);
That should help.

Related

Schema hasn't been registered for model "Product"

I'm trying to create a model "Product", but when I access that by the name "Product" in the Controller, it returns me this error.
Model Product
const mongoose = require('mongoose');
const ProductSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
url: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now()
}
});
mongoose.model('Product', ProductSchema);
Product Controller
const mongoose = require('mongoose');
const Product = mongoose.model('Product');
module.exports = {
async index(req, res) {
const products = await Product.find();
return res.json(products);
}
}
Export the model from 'Model Product' and require it inside your 'Product controller'. Like this:
Model Product:
const mongoose = require('mongoose');
const ProductSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
url: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now()
}
});
module.exports=mongoose.model('Product', ProductSchema);
Product Controller
const mongoose = require('mongoose');
const Product = require('path to model product.ex-../schemas/modelProduct')
module.exports = {
async index(req, res) {
const products = await Product.find();
return res.json(products);
}
}

How to auto delete ObjectId referances in mongodb

im trying to auto delete notifications referance from users ,when notification gets deleted
the userSchema looks like
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
notifications: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Notification",
},
],
});
module.exports = mongoose.model("User", userSchema);
The notification model looks like this
const mongoose = require("mongoose");
const notificationSchema = new mongoose.Schema({
type: String,
created: {
type: Date,
default: Date.now,
},
});
notificationSchema.pre("deleteOne", function (next) {
this.model("User").deleteOne({ notifications: this._id }, next);
});
module.exports = mongoose.model("Notification", notificationSchema);
when i try to delete notification i get an error ,which looks like
ObjectParameterError: Parameter "obj" to Document() must be an object, got User
also is there a way to auto delete it [referances of notification in user] using TTL for notifications
ok ,after a few try and error. I came up with this solution..
const mongoose = require("mongoose");
const notificationSchema = new mongoose.Schema({
type: String,
created: {
type: Date,
default: Date.now,
},
});
notificationSchema.pre("deleteOne", function (next) {
let id = this.getQuery()["_id"];
mongoose.model("User").findOne(
{
notifications: id,
},
(err, res) => {
const index = res.notifications.findIndex((x) => x._id == id);
res.notifications.splice(index, 1);
res.save();
next();
}
);
});
module.exports = mongoose.model("Notification", notificationSchema);
Can i make any improvements ?

Add new mongoDB document with object type

I'm totally new to mongoDB, just coming from MySQL, so I'm trying to add a new document to a mongo database in Node.js, I have the code working except when I have to include a custom object.
Here's my code:
router.post('/', async (req, res) => {
const book= new Book({
title: req.body.book.title,
year_published: req.body.book.year_published,
author: req.body.author // ==> here is the problem without it works fine (comes the full author via body parameter)
});
try {
const savedBook = await book.save();
res.json({
insertedBook: savedBook
});
} catch (err) {
//console.log("Error:" + err);
res.json({error: err});
}
});
The book and author models (simplified):
// ======= AUTHORS ================ //
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate-v2');
const schema = new mongoose.Schema({
name: {
type: String,
required:true
},
place_birth: {
type: String,
required:true},
});
schema.plugin(mongoosePaginate);
const Authors = mongoose.model('Authors',schema);
module.exports = Authors;
// ======= BOOKS ================ //
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate-v2');
var ObjectId = mongoose.Schema.Types.ObjectId;
const schema = new mongoose.Schema({
title: {
type: String,
required:true
},
year_published: {
type: String,
required:true},
author: [{
type: ObjectId,
ref: 'Authors',
required:false
}],
});
schema.plugin(mongoosePaginate);
const Books = mongoose.model('Books',schema);
module.exports = Books;
Data posting:
{
"book": {
"title": "Entrada con cuernos",
"year_published": "2020",
},
"author": {
"name": "Marcus",
"place_birth": "Moscow",
}
}
What's the proper way to insert a book document?
Thanks
When creating a new Book, Book.author should be a mongoose document, meaning the Author should exist in the mongoDB already.
You need to first save the Author in the DB, then pass it in Boot.author with it's Author._id property set
P.S.: Use singular words when describing your collections:
const Authors = mongoose.model('Authors',schema);
const Authors = mongoose.model('Author',schema); // recommended
mongoose will take care of the plural naming
The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural, lowercased version of your model name

Model automatically saves into a " (modelname)+s " collection

I'm using mongoose (last version , fresh install) for a MEAN architecture (mongo+express+angular+nodejs) and i'm approaching to save some data into my mongodb.
I have a db called "cogestione" and three collections: "ragazzi", "sedi" and "corsi".
I want to save a data of type Ragazzo in collection "ragazzi". I connect with:
mongoose.connect("mongodb+srv://admin:************.mongodb.net/cogestione?retryWrites=true", { useNewUrlParser: true })
.then(() => console.log("Connection to database correctly happened"))
.catch((err) => console.log(err))
and all goes smoothly. In another file i have the model:
const mongoose = require("mongoose");
const postSchema = mongoose.Schema(
{
nome: {
type: 'String'
},
cognome: {
type: 'String'
},
classe: {
type: 'String'
},
email: {
type: 'String'
}
}
);
module.exports = mongoose.model("ragazzo" , postSchema);
and i export it with the last line. Then , back in the app i send it to the db with:
const post = new Ragazzo({
nome: req.body.nome,
cognome: req.body.cognome,
classe: req.body.classe,
email: req.body.email
});
console.log(post);
post.save()
.catch((err)=>{console.log(err)});
res.status(201).json({message : "Post added"});
The problem is that it doesn't save my doc into "ragazzi" collection , but it creates a new collection called "ragazzos"... how can i tell mongoose to save it into a fixed collection?
Create your mongoose Schema like as bellow.
const mongoose = require("mongoose");
const postSchema = mongoose.Schema(
{
nome: {
type: 'String'
},
cognome: {
type: 'String'
},
classe: {
type: 'String'
},
email: {
type: 'String'
}
}, {collection: 'ragazzi'});
your problem is you use this line
module.exports = mongoose.model("ragazzo" , postSchema);
but not export the compiled model.. you should export the compiled model like this
const Post = module.exports = mongoose.model("ragazzo" , postSchema);
then in your router import it like so
const post = require("./models/Post"); // in your case keep your file path
const post = new Post({
nome: req.body.nome,
cognome: req.body.cognome,
classe: req.body.classe,
email: req.body.email
});
console.log(post);
post.save()
.catch((err)=>{console.log(err)});
res.status(201).json({message : "Post added"});
this will work the way you want it mate .. cheers

How do I match and post id to a comment in mongoose populate for find({})

I am trying to get comments from one collections and link them to their specific post.
What I want to do is find all of the posts instead of the collections THEN populate each of the commentid's in post collections with matching comments inside the comment collections.
I have set articleid to be the same as the post _id manually with an an ajax request function. However I am getting confused with how to properly use match in populate.
Ex. post _id 123, I want all comments with articleid, 123, but for multiple id's not just one.
I looked at the mongoose docs about populate and there wasn't anything as in depth as this example.
router.get('/displayPosts', (req, res) => {
Post.find({}, 'topic title url', () => {
})
.populate({
path: 'commentId',
// ---------------Where confused
// match: { postId: _id },
select: 'comment',
options: {limit: 5}
})
.sort({createdAt: 'desc'})
.then((data) => {
console.log(data);
res.send({response: data});
});
});
});
//when generating new docs
//getting this from bodyparser from button submit
const newComment = new Comments({
comment: req.body.userComment,
articleId: req.body.id
});
newComment.save();
const newArticle = new Article({
topic: data.topic,
title: data.title,
url: data.url
});
newArticle.save();
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Comments = require('./comments');
const PostSchema = new Schema({
topic: String,
title: String,
url: String,
commentId: [{type: Schema.Types.ObjectId, ref: 'Comments'}]
},
{
timestamps: true
});
const Post = mongoose.model('Post', ArticleSchema);
module.exports = Post;
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Post = require('./articles');
const CommentSchema = new Schema({
comment: String,
articleId: String
},
{
timestamps: true
});
const Comments = mongoose.model('Comments', CommentSchema);
module.exports = Comments;

Categories