how to pass the collection name dynamically in the mongoDB schema - javascript

Now can you guys please help me with how can I pass the dynamic value while creating the Schema? I want to modify the {CollectionName} in Schema.But I don't want to update the .env file again and again.
I want to pass it as a param
const CardSchema = new mongoose.Schema({
collectionName: {
type: String,
required: true,
}
});
console.log(tabelName);
module.exports = mongoose.model(`${CollectionName}`, CardSchema);
app.post("/form", async (req, resp) => {
const userCard = new CardSchema({
collectionName: req.body.collectionName,
cardName: req.body.cardName,
cardIndex: req.body.cardIndex,
content: req.body.content,
label: req.body.label,
});
await userCard.save();
console.log("user added");
resp.send(userCard);
});
'I did this but I don't think it is the best way
const CollectionName = process.env.COLLECTION_NAME;
'

Related

unable to push object returned from mongoose query

I am making a social media backend.
I save post added by the used in a Post model and user data in a User model.
GITHUB_REPO_LINK_AT_END
NOTE: UserSchema have a Schema.TypesOf.ObjectId Reference To POST Model. User_Model_&_Post_Model_are_provided_in_the_end
To get all posts of a particular user, I make a GET request to the route "/post" with body:
{ "id" : "6399d54c00308a2fe0bdf9fc"} //sending user id to fetct all the ID of the post from USER model, so i can then query the POST model for the posts
This the function I am getting problem with:
const getPost = async(req, res)=>{
if(req.body.id){
try {
const user = await User.findById(req.body.id).select('-_id post');
//THIS IS THE PART I NEED HELP WITH-------------------------------------------
const posts = await user.post.map(async(postID) => {
const result = await Post.findById(postID).select('-_id title body');
//console.log(result) THIS PRINTS THE CORRECT OBJ FROM DB
return result; //THIS RETURNS AN EMPTY OBJECT HERE
});
//----------------------------------------------------------------------------
res.status(200).json(posts);
} catch (error) {
console.log(error);
res.status(500).json({message: error.message});
}
}
};
when sending a GET request it returns an empty array with empty objects.//PS: no. of empty obj = actual no. of obj in DB
//This is the response
[{},{},{},{},{},{},{},{},{},{},{}]
{
//This is the user object
"_id": "6399d54c00308a2fe0bdf9fc",
"createdAt": "2022-12-14T13:52:40.483Z",
"name": "ShivamUttam",
"username": "Fadedrifleman",
"post": [
"6399d57200308a2fe0bdfa00",
"6399d5c400308a2fe0bdfa06",
"6399d5ca00308a2fe0bdfa0a",
"6399d5d600308a2fe0bdfa0e",
"6399de29e8aa8697299941c5",
"6399dec6e9b79ac66c59cd7a",
"6399df0dbea937f8b3365979",
"6399df31bea937f8b336597d",
"6399df31bea937f8b3365981",
"6399df32bea937f8b3365985",
"6399df33bea937f8b3365989"
],
"__v": 5
}
Model for USER and POST:
User:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
createdAt: {
type: Date,
default: Date.now()
},
name: {
type: String,
required: [true, 'name must be provided'],
},
username : {
type: String,
required: [true, 'Username must be provided'],
},
post:[{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post',
}],
});
module.exports = mongoose.model('User', userSchema)
Post:
const mongoose = require('mongoose')
const postSchema = new mongoose.Schema({
createdAt: {
type: Date,
default: Date.now()
},
title:{
type: String,
required: [true, "title cannot be empty"],
max: [20, "title cannot exceed 20 character"]
},
body: {
type: String,
max: [145, "body cannot exceed 145 character"],
},
tags:{
type: String,
},
});
module.exports = mongoose.model('Post', postSchema);
https://github.com/Fadedrifleman/socialMediaAppBackend/tree/master
Since you have used async callback function in the map method, a async function always return a promise, whatever the entity is returned by the function is wrapped inside a promise and that promise is returned.
If you want to use map function with async js code, you can try the following
const posts = await Promise.all(user.post.map(async(id)=>{
const result = await Post.findById(postID).select('-_id title body');
return result;
}));
and if you want to straightaway send the posts, you can also use .lean() method on posts, as in
await Post.findById(postID).select('-_id title body').lean()
You had some bugs that probably would interfere, I did a pull request to fix them: https://github.com/Fadedrifleman/socialMediaAppBackend/pull/1
But the main part would be this:
const getPost = async (req, res) => {
try {
if (req.body.id) {
const user = await User.findById(req.body.id);
await user.populate("post");
res.status(200).json(user.post);
return;
}
const posts = await Post.find({ access: 'public' }).select('-access');
res.status(200).json(posts);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

Api Post 400 Bad Request

I'm making a post API on a dummy node project; it worked fine there, but implemented the same API on the main project I got the 400 Bad request error while running this API on a post.
Route js
router.post("/add",(req, res) => {
const planName = req.body.planName;
const planPrice = req.body.planPrice;
const planMode = req.body.planMode;
const planStatus = req.body.planStatus;
const newAddon = new Addon({
planName,
planPrice,
planMode,
planStatus,
});
console.log("newAddon", newAddon)
newAddon.save()
.then(() => res.json("Addon added"))
.catch(err =>
res.status(400).json("Error in Add Addon route")
);
});
Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const addonsSchema = new Schema(
{
planId: {type: Number,required: true},
planName: {type: String,required: true},
planPrice: {type: Number,required: true},
planMode: {type: String, required:true},
planStatus: {type: String, required:true}, //active or inactive
},
{timestamps: true},
);
const Addon = mongoose.model("Addons", addonsSchema);
module.exports = Addon
index.js
const addonRouter = require('./routes/addon')
app.use('/addons',addonRouter)
Postman Screenshot
You'll need to provide planId as well in the payload, since you've defined required as true.
You've 2 ways to solve this:
Set the value of planId equal to _id field that mongodb creates automatically before inserting. You can do this with a preSave hook on the model.
addonsSchema.pre("save", (next) => {
// only triggered when creating new records
if (this.isNew) {
this.planId = this._id;
}
next();
});
And your type for planId should be ObjectId.
planId: {type: ObjectId,required: true},
Won't recommend but you can remove required attribute from planId.

How can I update 2 collections at the same time using Node.js/Mongoose/MongoDB

Thank you for taking your time reading this.
I am making blog app with Node.js/Mongoose/MongoDB. Currently, I'm struggling to figure out how to update 2 collections at the same time.
My userSchema has arrays of postSchema, and I would like to update both users and posts collections whenever I update documents.
My code is here:
const postSchema = new mongoose.Schema({
title: String,
content: String,
author: String
});
const Post = mongoose.model('Post', postSchema);
const userSchema = new mongoose.Schema({
username: String,
password: String,
displayName: String,
provider: String,
posts: [postSchema],
drafts: [postSchema]
});
const User = mongoose.model('User', userSchema);
app.post('/edit/:title', function (req, res) {
Post.findOneAndUpdate({ title: req.params.title }, {
title: req.body.title,
content: req.body.content
}, function (error, post) {
if (error) {
console.log(error);
} else {
res.redirect('/dashboard');
}
});
});
At the moment, my code only updates posts collection, and arrays of postSchema inside users collection stay the same. Could anyone help me how to solve this problem?
You can do it 2 ways
Option 1
.then() & .catch() block
Post.findOneAndUpdate({
Do your stuff here
}).then((result)=>{
Do your stuff here with result from step above
}).catch((err)=>{
Handle Error
});
Option 2
Use async/ await
async function (req, res) {
const postResult = await Post.findOneAndUpdate({ title: req.params.title }, {
title: req.body.title,
content: req.body.content
});
const userResult = await User.findOneAndUpdate({Do some stuff here});
if(!postResult || !userResult){
return new Error(...)
}
return
Since there is not much of code shared this cannot be used as is.. but the logic behind these options will remain the same even in your code ..

Will affect on performance the creating new schema at every functional call?

Based on my requirement I have to create new schema at every function call.
That actually works, but I am worry about its performance.
My code:
app.post('/', (req, res)=> {
const {query, data} = req.body;
doOperations(data, 'multiValueSearch', docs => {
const RootQueryType = GraphQLObjectType({
name: "RootQuery",
fields: {
users: {
type: GraphQLList(UserType),
resolve: ()=> docs
}
}
});
const schema = new GraphQLSchema({
query: RootQueryType
});
graphql(schema, query).then(result => res.json(result)));
});
});
The function doOperations is involved at any time users search their friends.
So in every search this doOperations gets called.
Is this a problem or is not concern will no affect on graphql performance ?
Why I am have to do this ? because the docs returns based on data I am passing to db.
Why I am have to do this? because the docs returns based on data I am passing to db.
No, that's not a reason to create a new schema on every call.
You should create a static schema that uses a resolver which takes the docs from the rootvalue that can be passed with every graphql query execute()ion.
In your case, you actually don't even need that. Instead of running doOperations for the whole endpoint, you should run it inside the resolver that produces the users and make data an argument:
const RootQueryType = GraphQLObjectType({
name: "RootQuery",
fields: {
users: {
type: GraphQLList(UserType),
args: {
filter: {
type: GraphQLList(ConditionType),
},
},
resolve(_, {filter}) {
return doOperations(filter, 'multiValueSearch');
}
}
}
});
const schema = new GraphQLSchema({
query: RootQueryType
});
app.post('/', (req, res)=> {
const {query, variables} = req.body;
graphql(schema, query, null, {}, variables).then(result => {
res.json(result);
}, err => {
console.error(err);
res.status(500).json({error: 'A problem occurred.'});
});
});

How to get the time a post request was made using Javascript in node.js

I'm making a basic blog application(I'm a newcomer to web development,so I'm building thisfor learning reasons, so nothing advanced), and when someone needs to publish something they head over to a"/compose" route. And when they publish a POST request is made to the server like this,
app.post("/compose",function(req,res){
const postTitle = req.body.postTitle;
const postCategory = req.body.postCategory;
const postBody = req.body.postBody;
const authorName = req.body.authorName;
if (postCategory === "movies"){
MoviePost.findOne({title: postTitle}, function(err, foundPost){
if(!err){
if (!foundPost){
const newPost = new MoviePost({
title: postTitle,
content: postBody,
category: postCategory,
author: authorName
});
newPost.save(function(err){
if(!err){
res.redirect("/");
}
});
} else {
res.send("Post title already exists!Revisit the compose page to publish anything else.")
}
} else {
console.log(err);
}
});
});
and it works fine as of now(I also use Body-Parser. But I also need to know the time the request was made so I can include the written time in the Blog Post. How can I go about achieving it?
If you're using mongoose, you can simply add an extra property to your schema:
const { Schema } = require("mongoose");
const MovieSchema = new Schema({
title: String,
content: String,
category: String,
author: String,
date: { type: Date: default: () => new Date() }
});
This will automatically add the date to the new document when it is saved to the database, so you don't have to do it manually.
I think I figured it out , I did it like this(I also updated the post Schema.),
const postCategory = req.body.postCategory;
const postBody = req.body.postBody;
const authorName = req.body.authorName;
const addedDate = new Date();
const addedTime = addedDate.toString();
if (postCategory === "movies"){
MoviePost.findOne({title: postTitle}, function(err, foundPost){
if(!err){
if (!foundPost){
const newPost = new MoviePost({
title: postTitle,
content: postBody,
category: postCategory,
author: authorName,
time : addedTime
});
newPost.save(function(err){
if(!err){
console.log(addedTime);
res.redirect("/");
}
});
} else {
res.send("Post title already exists!Revisit the compose page to publish anything else.")
}
} else {
console.log(err);
}
});
});

Categories