add a youtube video link in mongoose schema - mongodb

I am creating a video sharing platform where anyone can add youtube videos and their preferred image But for the backend I am using mongodb for that I am creating mongoose schema I need to add youtube video link to the schema which also validates whether it is a youtube video link or not so how can I achieve his task
const mongoose = require("mongoose");
const validate = require("validator");
const config = require("../config/config");
const videoSchema = mongoose.Schema(
{
title :{
type: String,
required: true,
trim: true,
},
genre:{
type: String,
required: true,
trim: true,
},
viewCount :{
type: Number,
default: config.default_view_count,
},
releaseDate :{
type : Date,
required: true,
default: Date.now,
},
votes :{
type: [Object],
upvotes: {
type: Number,
},
downvotes:{
type: Number,
}
},
contentrating: {
type: Number,
required: true,
trim: true,
},
previewimage:{
type: 'image/png',
required: true,
}
},
//create createdAt and updateAt field automatically
{
timestamps: true,
}
)
const Video = mongoose.model('Video',videoSchema)
module.exports = {Video};

If your link is just a simple youtube link and you're looking to check it's validity, you can use the youtube API and request information about the video pointed to by that link.
There's an example that requests information about a specific video :
https://developers.google.com/youtube/v3/getting-started#Sample_Partial_Requests
If no information or an error is returned, then you know it's an invalid link.

I guess an easy way is to just validate if the video link starts with https://www.youtube.com/. You can add a new field to your Schema Model and add validation to that field. If validation fails, document will not be stored and an error will be thrown.
You can add a new youtube_video_link field in your Schema Model like this:
const mongoose = require("mongoose");
const validate = require("validator");
const config = require("../config/config");
const videoSchema = mongoose.Schema(
{
title :{
type: String,
required: true,
trim: true,
},
genre:{
type: String,
required: true,
trim: true,
},
viewCount :{
type: Number,
default: config.default_view_count,
},
releaseDate :{
type : Date,
required: true,
default: Date.now,
},
votes :{
type: [Object],
upvotes: {
type: Number,
},
downvotes:{
type: Number,
}
},
contentrating: {
type: Number,
required: true,
trim: true,
},
previewimage:{
type: 'image/png',
required: true,
},
youtube_video_link: {
type: String,
validate: {
validator: function(v) {
return /^https:\/\/www.youtube.com\/.*$/.test(v);
},
message: props => `${props.value} is not a valid youtube link.`
},
required: [true, 'Youtube video link is required.']
}
},
//create createdAt and updateAt field automatically
{
timestamps: true,
}
)
const Video = mongoose.model('Video',videoSchema)
module.exports = {Video};

Related

mongoose validator not working as expected

i want to add batch,department,stream,id fields to the schema depending if usertype is “Student”,i do not understand why,but sometimes it adds the fields sometimes not.forexample if i created a user with usertype “Student” first it does not add the fields,but after that when i created a user with usertype “Teacher” or “Admin” it asks me the fields are required meaning it add the fields and this happens vice versa.why any way to fix this issue?please help guys.
what i have tried well,i have asked chatGpt but no answers i mean just the answers do not solve the issue.
here is the code
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema(
{
fullName: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
userType: {
type: String,
required: true,
},
phoneNumber: { type: String, required: true },
password: { type: String, required: true },
approved: { type: Boolean, default: true },
},
{
timestamps: true,
}
);
userSchema.pre("validate", function (next) {
if (this.userType === "Student") {
this.constructor.schema.add({
batch: {
type: Number,
required: true,
},
department: {
type: String,
required: true,
},
stream: {
type: String,
required: true,
},
id: { type: String, required: true }, //, unique: true
});
}
next();
});
const userModel = mongoose.model("users", userSchema);
module.exports = userModel;

Mongoose and MongoDB, how to create relation betwean two models with multiple references?

everyone.
So I have this "blog" app where users can create posts with images.
How my app works is that it loads different posts by userID.
So I have a relation bewtean user and post by the user and post _id, however I also want to save username into the post schema and created ralation that way. Is it possible to do such thing ?
This is my User schema
import mongoose from "mongoose";
import mongooseUniqueValidator from "mongoose-unique-validator";
const Schema = mongoose.Schema;
const validator = mongooseUniqueValidator;
const user_Schema = new Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, minlength: 3 },
user_image: { type: String },
posts: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Post' }], //relation bewtean post and user
},{ timestamps: true }
);
user_Schema.plugin(validator);
export const USER: mongoose.Model<any> = mongoose.model("User", user_Schema);
And this is my Post Schema:
import mongoose from "mongoose";
const Schema = mongoose.Schema;
const post_Schema = new Schema({
title: { type: String, required: true, },
description: { type: String, required: true, },
imageURL: { type: String },
creator_id: { type: mongoose.Types.ObjectId, required: true, ref: 'User' },
},
{ timestamps: true }
);
export const POST: mongoose.Model<any> = mongoose.model("Post", post_Schema);
However this is what I want the post to contain, I want the post to contain ID of the user who created it and the name of the user who created it.
However I do not know how to create it. So this is how I want my Post schema to look like, I want to be able to save both the user ID and username into the post.
const Schema = mongoose.Schema;
const post_Schema = new Schema({
title: { type: String, required: true, },
description: { type: String, required: true, },
imageURL: { type: String },
user: {
creator_id: { type: mongoose.Types.ObjectId, required: true, ref: 'User' }, //relation bewtean post and user
creator_name: { <soemthing here>, ref: 'User' }, //relation bewtean post and user
},
},
{ timestamps: true }
);
export const POST: mongoose.Model<any> = mongoose.model("Post", post_Schema);
If you want to retrieve the creator name using the ref is the correct approach, you just need to populate the Post documents when you are retrieving them with:
const posts = await Post.find({}).populate('creator').exec()
for (const post of posts) {
// Every post should contain the creator user properties
console.log(post.creator._id, post.creator.username)
}
Just make sure that your ref fields are of type mongoose.Schema.Types.ObjectId:
const post_Schema = new Schema(
{
title: { type: String, required: true },
description: { type: String, required: true },
imageURL: { type: String },
creator: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
},
{ timestamps: true }
);
export const POST: mongoose.Model<any> = mongoose.model('Post', post_Schema);

Populate a property of a mongoose schema with all the data in another collection

I have a model with articles, and would like to populate an array of data with all the documents in a collection.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ArticlesSchema = new mongoose.Schema({
path: {
type: String,
required: true,
unique: true,
},
base_headline: {
type: String,
required: true,
},
intro: {
type: String,
required: true,
},
featured_image: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
platform_filter: {
type: String,
},
free_filter: {
type: String,
},
content_type: {
type: String,
required: true,
},
data: [{ type: Schema.Types.ObjectId, ref: 'DesignProducts' }],
date: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model('Articles', ArticlesSchema);
The data property should be populated with all documents in the DesignProducts collection.
I tried running this but the data array is still empty:
Article.findOne({ path: slug }).populate('data').exec();
Here is what the designProducts model looks like:
const mongoose = require('mongoose');
const DesignProductsSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
},
intro: {
type: String,
required: true,
},
website: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model('DesignProducts', DesignProductsSchema);
This array should be populated with all the documents in the DesignProducts collection:

MongoDB: Set and get Sub Document Schema

I'm using mongoose and I have users collection shown below, but I now want to allow the user to save a number of articles, an article has a title, subtitle, and body, One user can have many articles.
How can I restructure the users collection to allow the articles to be added
const userSchema: Schema = new Schema(
{
email: { type: String, required: true, unique: true },
fullName: { type: String, required: true },
password: { type: String, required: true },
},
{
timestamps: true,
}
);
I'm using the below to set new data to the user's collection, how do I adapt it to allow me to set and get the new articles detailed above?
const confirmed = await userModel
.findOneAndUpdate(
{ email },
{
$set: { password },
}
)
.exec();
You can set the option strict: false and add(save) new fields to your schema.
const userSchema: Schema = new Schema(
{
email: { type: String, required: true, unique: true },
fullName: { type: String, required: true },
password: { type: String, required: true },
},
{
strict: false,
timestamps: true,
}
);
Here is the docs

Push a sub-subdocument on a Mongoose Schema [duplicate]

This question already has answers here:
Mongodb $push in nested array
(4 answers)
Closed 3 years ago.
Consider these 3 schemas and hierarchy: A Project has multiple Stages, a Stage has multiple Events.
For pushing a new Stage into a Project, I do this:
Project.findOneAndUpdate(
{ slug: projectSlug },
{ $push: { stages: myNewStage } },
).then((post) => res.status(201).json({
message: 'stage created successfully',
data: post,
})).catch((error) => {
return res.status(500).json({
code: 'SERVER_ERROR',
description: 'something went wrong, Please try again',
});
});
But, how can I push a new event into a Stage? As far as I've seen, a subdocument does not have the same properties as a document (such as find, findAndUpdate).
My actual schemas:
PROJECT SCHEMA
const mongoose = require('mongoose');
const Stage = require('./Stages').model('Stages').schema;
const projectSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
description: {
type: String,
},
slug: {
type: String,
trim: true,
required: true,
lowercase: true,
unique: true,
},
clientSlug: {
type: String,
trim: true,
required: true,
lowercase: true,
},
stages: [Stage],
startDate: {
type: Date,
trim: true,
required: true,
},
endDate: {
type: Date,
trim: true,
required: false,
},
},
{
timestamps: true,
});
module.exports = mongoose.model('Projects', projectSchema);
STAGE SCHEMA
const mongoose = require('mongoose');
const Event = require('./Events').model('Events').schema;
const stageSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
description: {
type: String,
},
slug: {
type: String,
trim: true,
required: true,
lowercase: true,
unique: true,
},
clientSlug: {
type: String,
trim: true,
required: true,
lowercase: true,
},
projectSlug: {
type: String,
trim: true,
required: true,
lowercase: true,
},
events: [Event],
},
{
timestamps: true,
});
module.exports = mongoose.model('Stages', stageSchema);
EVENT SCHEMA
const mongoose = require('mongoose');
const Comment = require('./Comments').model('Comments').schema;
const eventSchema = new mongoose.Schema({
_id: {
type: String,
trim: true,
lowercase: true,
},
userEmail: {
type: String,
trim: true,
required: true,
lowercase: true,
},
text: {
type: String,
},
imgUrl: {
type: String,
},
documentUrl: {
type: String,
},
stageSlug: {
type: String,
trim: true,
required: true,
lowercase: true,
},
clientSlug: {
type: String,
trim: true,
required: true,
lowercase: true,
},
projectSlug: {
type: String,
trim: true,
required: true,
lowercase: true,
},
comments: [Comment],
},
{
timestamps: true,
});
module.exports = mongoose.model('Events', eventSchema);
To push a new event into your stages array given that you have the projectSlug and stageSlug, you can do this:
Project.findOneAndUpdate(
{
$and: [
{ slug: projectSlug },
{ 'stages.slug': stageSlug },
]
},
{
$push: { 'stages.$.events': newEvent }
}
)
.then(() => {})
.catch(() => {});