본문 바로가기
프로젝트/유튜브 클론코딩

mongodb and mongoose 6: pre, middleware, static

by 두 그루 2023. 2. 17.

Video model의 정보 중 하나인 hashtag들을 #를 붙인 문자열의 배열으로 upload, update때마다 정리해야 한다. controller에 복사붙여넣기 말고, 함수를 만들어 활용하는 방법을 기록한다.

 

1. pre(mongoose's middleware)

import mongoose from "mongoose";
const videoSchema = new mongoose.Schema({
    title: { type: String, required: true, trim: true, maxLength: 30 },
    description: { type: String, required: true, trim: true, maxLength: 100 },
    createdAt: {type: Date, required: true, default: Date.now },
    hashtags: [{ type: String, required: true, trim: true }],
    meta: {
        views: { type: Number, required: true, default: 0},
        rating: { type: Number, required: true, default: 0},
    }
});

// Model 전에 정의
videoSchema.pre("save", async function() {
    this.hashtags = this.hashtags[0]
        .split(",")
        .map(word => word.startsWith("#") ? word : `#${word}`);
});

const Video = mongoose.model("Video", videoSchema);

export default Video;

https://github.com/soaringwave/wetube/commit/31a0ebccee2bc3d2391f21fd35f5b26d695d681e

https://mongoosejs.com/docs/middleware.html

 

Mongoose v6.9.2: Middleware

Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions. Middleware is specified on the schema level and is useful for writing plugins. Mongoose has 4 types of middleware: document middl

mongoosejs.com

 

 

 

 

2. function

Video.js

import mongoose from "mongoose";

export const formatHashtags = (hashtags) => {
	return hashtags.split(",").map((word) => (word.startsWith("#") ? word : `#${word}`));
};

const videoSchema = new mongoose.Schema({
    title: { type: String, required: true, trim: true, maxLength: 30 },
    description: { type: String, required: true, trim: true, maxLength: 100 },
    createdAt: {type: Date, required: true, default: Date.now },
    hashtags: [{ type: String, required: true, trim: true }],
    meta: {
        views: { type: Number, required: true, default: 0},
        rating: { type: Number, required: true, default: 0},
    }
});

const Video = mongoose.model("Video", videoSchema);

export default Video;

videosController.js

import Video, { formatHashtags } from "../model/Video";

// ...

export const postEdit = async (req, res) => {
    const id = req.params.id;
    const { title, description, hashtags } = req.body;
    const video = await Video.exists({ _id: id });
    if (!video) {
        return res.render("404", { pageTitle: "Video not found" });
    }
    await Video.findByIdAndUpdate(id, {
        title,
        description,
        // here
        hashtags: formatHashtags(hashtags),
    })
    return res.redirect(`/videos/${id}`);
}
export const postUpload = async (req, res) => {
    const { title, description, hashtags } = req.body;
    try {
        await Video.create({
            title,
            description,
            // here
            hashtags: formatHashtags(hashtags),
        });
    } catch(error) {
        const errorMsg = error._message;
        return res.render("upload", { pageTitle: "Uploading video", errorMsg: errorMsg });
    }
    return res.redirect("/");
}

 

 

 

3. static

Video.js

import mongoose from "mongoose";

const videoSchema = new mongoose.Schema({
    title: { type: String, required: true, trim: true, maxLength: 30 },
    description: { type: String, required: true, trim: true, maxLength: 100 },
    createdAt: {type: Date, required: true, default: Date.now },
    hashtags: [{ type: String, required: true, trim: true }],
    meta: {
        views: { type: Number, required: true, default: 0},
        rating: { type: Number, required: true, default: 0},
    }
});

videoSchema.static("formatHashtags", function (hashtags) {
    return hashtags.split(",").map((word) => (word.startsWith("#") ? word : `#${word}`));
});

const Video = mongoose.model("Video", videoSchema);

export default Video;

videosController.js

import Video from "../model/Video";

// ... 

export const postEdit = async (req, res) => {
    const id = req.params.id;
    const { title, description, hashtags } = req.body;
    const video = await Video.exists({ _id: id });
    if (!video) {
        return res.render("404", { pageTitle: "Video not found" });
    }
    await Video.findByIdAndUpdate(id, {
        title,
        description,
        // here
        hashtags: Video.formatHashtags(hashtags),
    })
    return res.redirect(`/videos/${id}`);
}
export const postUpload = async (req, res) => {
    const { title, description, hashtags } = req.body;
    try {
        await Video.create({
            title,
            description,
            // here
            hashtags: Video.formatHashtags(hashtags),
        });
    } catch(error) {
        const errorMsg = error._message;
        return res.render("upload", { pageTitle: "Uploading video", errorMsg: errorMsg });
    }
    return res.redirect("/");
}

https://mongoosejs.com/docs/api/schema.html#schema_Schema-static

 

Mongoose v6.9.2: Schema

Parameters: [definition] «Object|Schema|Array» Can be one of: object describing schema paths, or schema to copy, or array of objects and schemas [options] «Object» Inherits: Schema constructor. const child = new Schema({ name: String }); const schema =

mongoosejs.com

 

이렇게 하면 import, export 할 필요없다. 그리고 Video.function처럼 설정할 수 있다.

 

https://github.com/soaringwave/wetube/commit/c5751d4535495fba8b2252d146882cdd02c89a83

댓글