MongoDB


🌭 장단점

  • 장점
  • 단점
  • 🥗 데이터 삽입

  • DB명을 쓰고 collection 명을 써서 생성하고, insertOne을 이용해 하나의 데이터를 삽입할 수 있다.
  • 아래 코드는 콜백을 활용한 방법이다.
  • const { MongoClient, ServerApiVersion } = require('mongodb');
    const uri =
    'mongodb+srv://j56237:qwer1234@cluster0.03qkgmh.mongodb.net/?retryWrites=true&w=majority';
    const client = new MongoClient(uri, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    serverApi: ServerApiVersion.v1,
    });
    client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, result) => {
    if (deleteErr) throw deleteErr;
    console.log(result);
    test.insertOne(
    {
    name: 'JKE',
    nickName: 'goorm',
    },
    (insertErr, result) => {
    console.log(result);
    const findCursor = test.find({});
    findCursor.toArray((err, data) => {
    console.log(data);
    });
    },
    );
    });
    });
  • 삽입한 데이터는 Atlas에서 확인할 수 있다.
  • find() 안에 객체가 빈 객체이므로 가지고 있는 모든 데이터를 찾는다.
  • 콜백은 이용한 방법은 코드의 수정이 용이하지는 않다는 것을 알 수 있다.
  • insertOne

  • 하나의 도큐먼트를 삽입한다.
  • client.connect((err) => {
    const test = client.db("kdt5").collection("test");
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    test.insertOne(
    {
    name: "pororo",
    age: 5,
    },
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    }
    );
    });
    });
  • 위쪽 deleteMany는 빈 객체를 가지고 있으므로 모든 데이터를 지우는 코드이다.
  • 첫번째 인자에는 객체 데이터 / 두번째 인자에는 Err와 Result를 가진 콜백함수를 가진다.
  • insertMany

  • 여러 도큐먼트를 한번에 삽입한다.
  • 삽입할 도큐먼트는 배열에 담긴 객체 형태로 전달된다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    },
    );
    });
    });

    🍞 데이터 삭제

    deleteOne

  • 조건을 만족하는 가장 처음의 도큐먼트 하나를 삭제한다.
  • 조건은 객체 형태로서 deleteOne의 첫번째 인자로 전달한다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    test.deleteOne({ name: 'crong' }, (deleteOneErr, deleteOneResult) => {
    if (deleteOneErr) throw deleteOneErr;
    console.log(deleteOneResult);
    });
    },
    );
    });
    });
  • name이 ‘crong’인 값을 지워준다.
  • 뽀로로와 루피만 DB에 남게된다.
  • deleteMany

  • 조건을 만족하는 모든 도큐먼트를 삭제한다.
  • 조건은 객체 형태로서 deleteOne의 첫번째 인자로 전달하면 된다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    test.deleteMany(
    { age: { $gte: 5 } },
    (deleteManyErr, deleteManyResult) => {
    if (deleteManyErr) throw deleteManyErr;
    console.log(deleteManyResult);
    },
    );
    },
    );
    });
    });
  • gte는 Greater Than Eqaul의 약자로 크거나 작을때를 뜻한다.
  • 따라서 위 코드는 age가 5이상이면 지우게 된다.
  • 크롱만 DB에 남게된다.
  • 🧈 데이터 수정

    updateOne

  • 조건을 만족하는 가장 처음의 도큐먼트 하나를 수정한다.
  • 조건은 첫번째 인자로 전달하고, 변경점은 두번째 인자로 전달한다.
  • 변경부분은 $set:을 사용한다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    test.updateOne(
    { name: 'loopy' },
    { $set: { name: '루피' } },
    (updateOneErr, updateOneResult) => {
    if (updateOneErr) throw updateOneErr;
    console.log(updateOneResult);
    },
    );
    },
    );
    });
    });
  • 이렇게 되면 loopy만 이름이 한글 ‘루피’로 변하게 된다.
  • updateMany

  • 조건을 만족하는 모든 도큐먼트를 수정한다.
  • 조건은 첫번째 인자로 전달하고, 변경점은 두번째 인자로 전달한다.
  • 변경부분은 $set:을 사용한다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    test.updateMany(
    { age: { $gte: 5 } },
    { $set: { name: '나이가 5살 이상인 친구들' } },
    (updateManyErr, updateManyResult) => {
    if (updateManyErr) throw updateManyErr;
    console.log(updateManyResult);
    },
    );
    },
    );
    });
    });
  • 이렇게 하면 뽀로로와 루피의 name이 ‘나이가 5살 이상인 친구들’로 변경된다.
  • $set 말고 $inc도 존재한다. 이는 원래 값에 +를 시켜준다.
  • 🌯 데이터 검색

    findOne

  • 검색 조건을 만족하는 최초의 도큐먼트 하나를 찾아준다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    test.findOne({ name: 'loopy' }, (findOneErr, findOneData) => {
    if (findOneErr) throw findOneErr;
    console.log(findOneData);
    });
    },
    );
    });
    });
  • name이 ‘loopy’인 것을 찾아 console에 찍어준다.
  • find

  • findMany는 없고 find가 있다.
  • 조건에 맞는 도큐먼트를 전부 찾아준다.
  • 단, find는 독특한 특성을 가진다.
  • client.connect((err) => {
    const test = client.db('kdt5').collection('test');
    test.deleteMany({}, (deleteErr, deleteResult) => {
    if (deleteErr) throw deleteErr;
    console.log(deleteResult);
    test.insertMany(
    [
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ],
    (insertErr, insertResult) => {
    if (insertErr) throw insertErr;
    console.log(insertResult);
    const findCursor = test.find({ age: { $gte: 5 } });
    console.log(findCursor);
    findCursor.toArray((toArrErr, arrData) => console.log(arrData));
    },
    );
    });
    });
  • 이렇게 하면 5살 이상인 뽀로로와 루피만 가져오게 된다.
  • findCursor는 다음처럼 바로 사용할 수 있는 데이터가 아니다.
  • 🍠 비교식

  • $eq: 같을 때
  • $gt: 클 때
  • $gte: 크거나 같을 때
  • $lt: 작을 때
  • $lte: 작거나 같을 때
  • $ne: 다를 때
  • $in: 배열에 지정된 값 중 하나와 일치한 값
  • $nin: 배열에 지정된 값과 일치하지 않는 값
  • users.updateMany(
    {
    name: { $ne: 'loopy' },
    },
    {
    $set: {
    name: '루피 아님',
    },
    },

    🥯 논리식

  • $or: 조건들 중 하나라도 true면 반환
  • $and: 조건들이 모두 true일 때 반환
  • $not: 조건이 false일때 반환
  • $nor: 조건들이 모두 false일 때 반환
  • const cusor = users.find({
    $and: [{ age: { $gte: 5 } }, { name: 'loopy' }],
    });
    cursor.toArray((err, data) => {
    console.log(data);
    });

    🦴 Async / Await로 바꾸기

  • 콜백함수는 유지보수가 불편한 단점이 있다.
  • async function main() {
    try {
    await client.connect();
    const test = client.db('kdt5').collection('test');
    await test.deleteMany({});
    await test.insertOne({ name: 'pororo', age: 5 });
    await test.deleteMany({});
    await test.insertMany([
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ]);
    await test.deleteOne({ name: 'crong' });
    await test.deleteMany({});
    await test.insertMany([
    { name: 'pororo', age: 5 },
    { name: 'crong', age: 4 },
    { name: 'loopy', age: 6 },
    ]);
    await test.updateMany({ age: { $gte: 5 } }, { $set: { age: 10 } });
    const findCursor = test.find({ age: { $gte: 10 } });
    const dataArr = await findCursor.toArray();
    console.log(dataArr);
    } catch (err) {
    console.error(err);
    }
    }
    main();
  • async / await로 표현하면 다음과 같이 표현할 수 있다.
  • 코드 가독성이 좋아지고 양도 줄은 것을 볼 수 있다.
  • 🥃 Mongoose

  • MongoDB는 사용상의 제약이 전혀 없어서 편리하다.
  • 그러나 이 때문에 key의 값이 달라지는 등 버그가 발생할 수 있다.
  • 이는 Mongoose로 해결할 수 있다.
  • 스키마 생성

  • /models/user.js
  • const mongoose = require('mongoose');
    const { Schema } = mongoose;
    const userSchema = new Schema(
    {
    id: {
    type: String,
    required: true,
    unique: true,
    },
    password: {
    type: String,
    required: true,
    },
    createAt: {
    type: Date,
    default: Date.now,
    },
    },
    {
    collection: 'mongoose-user',
    },
    );
    module.exports = mongoose.model('User', userSchema);
  • 위처럼 타입과 required 등을 정해줄 수 있다.
  • CRUD 쿼리

  • mongoDB와 모두 동일하지만 insertOne 대신 create를 사용하면 된다.