-
MongoDB 1 - Database 구조, Connection, NodeJS 서버에서 CRUDData Base/MongoDB 2024. 7. 12. 17:31
1. RDB와 MongoDB 계층구조 비교
2. Mongoose Connection
2.1. MongoDB 드라이버
https://www.mongodb.com/ko-kr/docs/drivers/
위 링크에 각 언어 별로 MongoDB를 제어할 수 있는 드라이버를 제공한다.
2.2. MongoDB 노드 드라이버
https://www.mongodb.com/ko-kr/docs/drivers/node/current/
2.3. MongoDB 노드 드라이버를 사용할 수 있게하는 npm 모듈
https://www.npmjs.com/package/mongodb
해당 모듈을 다운받아서 사용해도 된다. 하지만 mongoose라는 것을 사용해서 MongoDB를 다루어 보자.
2.4. mongoose npm 모듈
https://www.npmjs.com/package/mongoose
mongoose를 사용하는 이유는 일단 mongoose는 내부적으로 npm mongDB 모듈을 사용하고 있다. 이에 더불어 mongoDB를 사용할때 편리한 편의 기능을 제공한다.
mongoose 설치
yarn add mongoose
mongoose 연결 코드
import { connect } from 'mongoose'; const MONGO_URI = 'mongodb+srv://admin:...Cluster'; let mongodbConnection = await connect(MONGO_URI); console.log(mongodbConnection);
3. Node.js 서버에서 MongoDB CRUD
3.1. UserSchema 만들기
User.js
import { model, Schema } from "mongoose"; const UserSchema = new Schema({ username: { type:String, required: true}, name:{ first:{type: String, require: true}, last:{type: String, require: true} }, //age: {type:Nmber} age:Number, email:String },{timestamps:true}) //mongoose에 모델 등록 export const User = model('user',UserSchema);
mongoose.Shema({},{})메서드를 사용해서 스키마를 만들면 mogoDB에 실제 collection을 만들기전에 해당 문법이 올바로 쓰여진 것인지 유효성 검사를 mongoose가 한번 더 체크한뒤 collection이 만들어 진다.
mongoose.Shema({},{}) 첫번째 파라미터는 어떤 key-value가 들어갈 것인지 정의한 객체가 들어가고, 두번 째 파라미터로는 스키마에대한 option 정보를 설정할 수 있다.
스키마 옵션
- timestamps : 데이터를 처음 생성했을때 created_at을 만들어 주고, 수정할때 마다 updated_at이라는 데이터를 수정해준다.
3.2. API와 MongoDB 연결하기
1) POST - /user
app.post( "/user", [ body("username").notEmpty().withMessage("username이 비어있습니다."), body("name").notEmpty().withMessage("name이 비어있습니다."), ], async (req, res) => { const validationError = validationResult(req); if (validationError.errors.length > 0) { return res.status(400).send({ err: validationError.array() }); } try { const user = new User(req.body); await user.save(); res.send(user); } catch (error) { console.log(error); return res.status(500).send({ err: error.message }); } } );
result
{ "username": "Tree", "name": { "first": "Toast", "last": "Lemon" }, "age": 31, "email": "lemon0@example", "_id": "6690db740f72c22c12da2c31", "createdAt": "2024-07-12T07:29:56.478Z", "updatedAt": "2024-07-12T07:29:56.478Z", "__v": 0 }
- __v : save를 할 때 마다 숫자가 올라간다.
2) GET - /user
app.get("/user", async (req, res) => { try { const users = await User.find({}); return res.send({ users }); } catch (error) { console.log(error); return res.status(500).send({ err: error.message }); } });
result
{ "users": [ { "name": { "first": "Sam", "last": "Kim" }, "_id": "6690db550f72c22c12da2c2f", "username": "Pasta", "age": 29, "email": "podo12340@example", "createdAt": "2024-07-12T07:29:25.526Z", "updatedAt": "2024-07-12T07:29:25.526Z", "__v": 0 }, { "name": { "first": "Toast", "last": "Lemon" }, "_id": "6690db740f72c22c12da2c31", "username": "Tree", "age": 31, "email": "lemon0@example", "createdAt": "2024-07-12T07:29:56.478Z", "updatedAt": "2024-07-12T07:29:56.478Z", "__v": 0 } ] }
3) GET - /user/userId
import { isValidObjectId } from "mongoose"; /** * GET - param userId에 해당하는 user 반환 */ app.get("/user/:userId", async (req, res) => { const { userId } = req.params; try { if (!isValidObjectId(userId)) return res.status(400).send({ err: "Invalid userId" }); const user = await User.findOne({ _id: userId }); return res.send({ user }); } catch (err) { return res.status(500).send({ err: error.message }); } });
4) DELETE - /user/userId
import { isValidObjectId } from "mongoose"; /** * DELETE - userId삭제 */ app.delete("/user/userId", async (req, res) => { try { const { userId } = req.params; if (!isValidObjectId(userId)) return res.status(400).send({ err: "Invalid userId" }); const users = await User.findOneAndDelete({ _id: userId }); return res.send({ users }); } catch (error) { console.log(error); return res.status(500).send({ err: error.message }); } });
findOneAndDelete()메서드는 해당하는 document가 있을때는 삭제한 객체를 없을 경우 null을 return한다.
3.3 특정 속성 Unique Index로 만들기
import { model, Schema } from "mongoose"; const UserSchema = new Schema( { //⭐ unique: true 값 설정 username: { type: String, required: true, unique: true }, name: { first: { type: String, require: true }, last: { type: String, require: true }, }, //age: {type:Nmber} age: Number, email: String, }, { timestamps: true } ); //mongoose에 모델 등록 export const User = model("user", UserSchema);
unique: true 설정을 통해서 username도 unique값이 된 것을 Compass에서 확인할 수 있다.
{ "err": "E11000 duplicate key error collection: BlogService.users index: username_1 dup key: { username: \"Tree\" }" }
위 설정을 한다음에 기존에 username이 이미 지정되어 있는 Tree로 다시 user를 생성하려고 하면 다음과 같은 error 메시지를 반환하면 user가 생성되지 않는다. 다만 이미 기존에 중복인 되는 값이 있는 속성이 이미 있는 경우 Unique index로 지정할 수 없다.
[출처 - mongoDB기초부터 실무까지(feat. Node.js), 저 김시훈]
'Data Base > MongoDB' 카테고리의 다른 글
Mongo DB - Compass CLI로 기본적인 CRUD (0) 2024.07.12 MongoDB - 개념설명, 초기 설정, 데이터 저장·조회 (0) 2024.04.25