풀스택 맛보기7-MongoDB

  1. MongoDB
    1. 명령어
      1. 상태 확인
        1. db 상태
        2. collection 상태
      2. db 사용
      3. 삭제
        1. DB 삭제
        2. collection 삭제
  2. Mongoose
    1. DB 연결
      1. SchemaTypes
      2. Mongoose Query
        1. Model.exists({})
        2. Model.find()
        3. Model.findById()
        4. Model.create()
        5. Model.findByIdAndUpdate()
        6. Model.findOneAndUpdate()
        7. Model.findByIdAndDelete()
    2. Mongoos Middleware
    3. Call back 함수
      1. function 속의 function
    4. Promise
      1. async & await
      2. try & catch
    5. DB에 저장하기

MongoDB

  • Json 형식과 같은 문서 기반(document-based) 데이터베이스. //일반적으로 sql based

사용법 (WSL 기준) sudo mongod --dbpath ~/data/db

다른 프롬프트 mongo 입력 후 실행

명령어

상태 확인

db 상태

show dbs

collection 상태

collection 확인 show collections

db 사용

use [DB 이름]

삭제

DB 삭제

use [DB 이름] db.dropDatabase()

collection 삭제

db.[삭제할 collection 이름].drop()

Mongoose

  • node.JS와 MongoDB의 다리 역할을 하는 패키지.

🔧 npm install mongoose

src/db.js 생성 //server.js와 같은 폴더에 만들어줌

프롬프트창에 mongo 입력 후 상단에 있는 주소를 가져와서 적용.

DB 연결

  1. DB 연결 위치 설정 /src/db.js ```js import mongoose from “mongoose”;

mongoose.connect(“mongodb://127.0.0.1:27017/[사용할 DB명]”);

2. 서버에 db.js파일 import
src/server.js
```js
import "./db.js";
  1. 연결 여부와 에러를 메시지로 받기 /src/db.js ```js import mongoose from “mongoose”;

mongoose.connect(“mongodb://127.0.0.1:27017/agora”);

const db = mongoose.connection;

const handleOpen = () => console.log(“💡 Connected to DB 🔗”); const handleError = (error) => console.log(“DB Error”, error);

db.on(“error”, handleError); db.once(“open”, handleOpen);

💡once : 한번만 실행

### Model
- MongoDB에서 문서를 만들고 읽는다.
- Schema 정의에서 컴파일된 생성자이다.

src/models/Post.js 폴더와 파일 생성

#### Schema
- 데이터 형식을 지정한다.

src/models/Post.js
방식 1. 기본
```js
import mongoose, { mongo } from "mongoose";

const postSchema = new mongoose.Schema({
  title: String,
  content: String,
  createdAt: Date,
  hashtags: [{ type: String }],
  meta: {
    views: Number,
    likes: Number,
  },
});

const Post = mongoose.model("Post", postSchema);
export default Post;

방식 2. Type 추가

const postSchema = new mongoose.Schema({
  title: { type: String, required: true },
  content: { type: String, required: true },
  createdAt: { type: Date, required: true, default: Date.now },
  hashtags: [{ type: String }],
  meta: {
    views: { type: Number, default: 0, required: true },
    likes: { type: Number, default: 0, required: true },
  },
});

/src/server.js

import "./db.js";
import "./models/Post.js";

=> Post.js를 import 시키므로 show dbs를 통해 연결된 것을 확인할 수 있다.


=> db를 mongoose와 연결시켜서 post model을 인식시킨다.


SchemaTypes

스키마 타입 확인하기

trim

“He ll o !”.trim() => “Hello!”

사용 예시.

hashtags: [{ type: String, trim: true }]

Length

  • 문자열의 최대/최소 길이

minLength & maxLength

title: { type: String, required: true, minLength: 1, maxLength: 30 },

Mongoose Query

Mongoose Query 살펴보기

Model.exists({})
  • 필터에 따라 존재여부를 알 수 있다.

예시.

Model.exists({title: "hello"})
Model.exists({_id: [id]})

=> 존재여부에 따라 값 혹은 Null이 나온다.

Model.find()
const posts = await Post.find({}).sort({ createdAt: "desc" });

=> argument에 따라 오름차순, 내림차순 설정 가능

Model.findById()
  • 해당 id를 검색하고 정보를 가져온다.

예시. 해당 id를 가지고 있는 post 가져오기

const { id } = req.params;
const post = await Post.findById(id);
Model.create()
Model.findByIdAndUpdate()
Model.findOneAndUpdate()
Model.findByIdAndDelete()

예시. 게시물 삭제

export const deletePost = async (req, res) => {
  const { id } = req.params;
  await Post.findByIdAndDelete(id);
  return res.redirect("/");
};

💡 findByIdAndDelete(id) === findByIdAndDelete({_id:id})

Mongoos Middleware

postSchema.pre("save", async function () {
  console.log("We are about to save: ", this);
});

console.log 결과 =>

We are about to save:  {
  title: 'abc',
  content: 'abcde',
  hashtags: [ '#aa', '#bb', '#cc' ],
  meta: { views: 0, likes: 0 },
  _id: new ObjectId("630c01ab5071f4572543f50d"),
  createdAt: 2022-08-29T00:00:43.087Z
}

Call back 함수

function 속의 function

export const home = (req, res) => {
    console.log("Start");
  Post.find({}, (error, posts) => {
      console.log(posts);
      console.log("Hello");
  });
  console.log("Finish");
  return res.render("home", { pageTitle: "Ἀγορά", fakeUser: fakeUser, posts: [] });
};

=> find가 오래 걸린다면 순서가 꼬일 수 있다.

💡두번째 줄 {}은 모든 것을 의미한다.

⭐ 출력 순서(find가 오래걸린 경우) ⭐

Start
Finish
Hello
[]

=> Callback 함수의 특성에 따라 “Finish” 전에 “Hello”가 먼저 나온다.

Promise

async & await

  • await이 있다면 JS는 결과값을 받을 때까지 계속 기다려준다.
export const home = async (req, res) => {
    console.log("Start");
    const posts = await Post.find({});
    console.log(posts);
    console.log("Hello");
    console.log("Finish");
    return res.render("home", { pageTitle: "Ἀγορά", fakeUser: fakeUser, posts: [] });
};

⭐ 출력 순서 ⭐

Start
[]
Hello
Finish

=> call back 함수보다 더 직관적이다.

try & catch

  • try 부분을 실행하고 오류가 난다면 catch를 실행한다.
export const home = async (req, res) => {
  try {
    console.log("Start");
    const posts = await Post.find({});
    console.log(posts);
    console.log("Finish");
    return res.render("home", { pageTitle: "Ἀγορά", fakeUser: fakeUser, posts: [] });
  } catch {
    return res.render("Error");
  }
};

DB에 저장하기

  1. JS Object를 만들기

  2. 해당 Object를 저장 src/controllers/postController.js 방법 1. new, object, save

    export const postUpload = async (req, res) => {
      const { title, content, hashtags } = req.body;
      const post = new Post({
     title: title,
     content: content,
     createdAt: Date.now(),
     hashtags: hashtags.split(",").map((word) => `#${word}`),
     meta: {
       views: 0,
       likes: 0,
     },
      });
      await post.save();
      return res.redirect("/");
    };
    

    => 직접 save를 해줘야 한다.

방법 2. create

export const postUpload = async (req, res) => {
  const { title, content, hashtags } = req.body;
  await Post.create({
    title: title,
    content: content,
    createdAt: Date.now(),
    hashtags: hashtags.split(",").map((word) => `#${word}`),
    meta: {
      views: 0,
      likes: 0,
    },
  });
  return res.redirect("/");
};

=> 따로 save할 필요가 없다.