npm install mongoose
mongoose.connect()
함수를 사용해서 연결할 수 있다. 연결 형식은 다음과 같다.mongoose.connect('mongodb://username:password@host:port/database', options)
mongoose.connect('mongodb://root:1234@localhost:27017/admin', {dbName: 'dev'})
const mongoose = require("mongoose");
const connectDB = async () => {
try {
// 콘솔에서 쿼리 내용을 확인할 수 있도록 디버그 모드 활성화
mongoose.set("debug", true);
// mongodb://[사용자이름]:[비밀번호]@호스트:포트번호/데이터베이스
await mongoose.connect("mongodb://root:1234@localhost:27017/admin", {
dbName: "dev", // 접속할 데이터베이스
});
} catch (err) {
if (err) {
console.error("MongoDB 연결 에러", err);
} else {
console.log("MongoDB 연결 성공", "localhost:27017/admin");
}
}
};
// MongoDB 연결 시 에러가 있을 때 발생하는 이벤트 리스너
mongoose.connection.on("error", (err) => {
console.error("MongoDB 연결 에러", err);
});
// MongoDB 연결이 종료되었을 때 발생하는 이벤트 리스너
mongoose.connection.on("disconnected", () => {
console.error("MongoDB 연결이 종료되어 연결을 재시도합니다.");
connect();
});
module.exports = connectDB;
createConnection()
함수를 사용한다.const mongoose = require('mongoose');
const conn1 = mongoose.createConnection('mongodb://localhost/mydb1');
const conn2 = mongoose.createConnection('mongodb://localhost/mydb2');
mongoose에서 스키마는 MongoDB 컬렉션에 들어가는 문서 내부의 각 필드가 어떤 형식으로 되어 있는지 정의하는 객체이다. mongoose가 MongoDB의 데이터베이스에서 실제 작업을 처리하기 위해 모델(model)이란 것을 사용하는데, 이 모델은 스키마를 사용해서 만들 수 있다. 모델은 MongoDB의 데이터에 대한 조회, 생성, 수정, 삭제와 같은 처리를 할 수 있는 다양한 함수를 내장하고 있다.
스키마를 정의할 때 문서의 각 필드에 대해서는 다음과 같은 옵션을 사용할 수 있다.
MongoDB를 설치하고 todos라는 컬렉션을 생성하였고 다음과 같은 Document를 추가했다.
{
"task": "test task",
"importance": "high"
}
필드명 | type | required | unique | default |
---|---|---|---|---|
task | String | true | ||
importance | String | true |
스키마는 다음과 같은 타입을 지원한다.
mongoose 폴더에 models 폴더를 만들고 todo.model.js 파일을 생성하고 다음 코드를 작성한다.
const mongoose = require("mongoose");
const { Schema } = mongoose;
const todoSchema = new Schema(
{
task: {
type: String,
required: true,
},
importance: {
type: String,
required: true,
},
},
{
timestamps: true,
}
);
// 스키마를 사용해서 모델 생성
const TodoModel = mongoose.model("Todo", todoSchema);
module.exports = TodoModel;
mongoose 모듈에서 Schema 생성자를 사용해서 스키마를 정의한다. 이때, _id
필드는 제외하고 나머지 필드에 대해서만 작성한다. MongoDB에서는 컬렉션에 새로운 문서가 추가될 때마다 자동으로 _id
에 유일한 키 값이 생성된다.
mongoose 모델은 다음과 같이 mongoose.model()
함수를 사용해서 생성할 수 있다.
const TodoModel = mongoose.model("Todo", todoSchema);
mongoose.model()
함수는 두 개의 파라미터를 가지고 있다. 첫 번째 파라미터는 스키마 이름이고, 두 번째 파라미터는 스키마 객체다. 일반적으로 스키마 이름의 첫 문자와 모델을 할당하는 변수명의 첫 문자는 대문자를 사용한다.
여기서 중요한 것은 스키마 이름이 정의되면 MongoDB의 데이터베이스에서 스키마 이름의 소문자 복수 형태로 컬렉션이 만들어진다는 것이다. 예를 들어, 스키마 이름이 'Todo'이면 MongoDB의 데이터베이스에 'todos'라는 이름으로 컬렉션이 만들어진다. 이미 동일한 컬렉션이 있다면 해당 컬렉션을 사용하게 된다.
// index.js
const express = require("express");
const cors = require("cors");
const connectDB = require("./mongoose/connectDB"); // mongoose 폴더의 index.js
const apiRouter = require("./routes/api.route");
const app = express();
const port = 8080;
connectDB(); // MongoDB 연결
app.use(cors());
app.use(express.json());
// 기본 경로로 /api 사용
app.use("/api", apiRouter);
app.listen(port, () => {
console.log(`서버가 실행됩니다. http://localhost:${port}`);
});
// controllers/todo.controller.js
const TodoModel = require("../mongoose/models/todo.model");
const getTodos = async (req, res) => {
try {
// localhost:8080/todos 접속 시 실행
const todos = await TodoModel.find(); // 별도의 조건 없이 todos 컬렉션이 모든 문서 조회
return res.status(200).json({
status: "success",
message: "전체 todo 목록 불러오기 성공",
data: {
todos,
},
});
} catch (error) {
res.status(500).json({
status: "error",
message: "Error fetching todos",
error: {
code: 500,
message: "Internal Server Error",
error,
},
});
}
};
module.exports = {
getTodos
};
find()
함수는 데이터 조회를 위한 함수다. 현재는 컬렉션에 문서가 한 건만 등록되어 있기 때문에 별도의 조회 조건 없이 함수를 호출했다.await Todos.find();
find()
함수는 다음과 같은 파라미터로 구성되어 있다.
// 전체 문서를 모두 조회한다.
await MyModel.find({});
// name이 john이고, age가 18보다 큰 문서를 조회한다.
await MyModel.find({ name: 'john', age: { $gte: 18 }}).exec();
// 쿼리를 실행하고, 콜백 함수로 데이터를 전달한다.
MyModel.find({ name: 'john', age: { $gte: 18 }}, (err, docs) => {});
// LIKE 검색. name에 john을 포함한 문서를 가져오되, name, email 2개의 필드만을 가져온다.
await MyModel.find({ name: /john/i }, 'name email').exec();
// 쿼리를 실행하고, 첫 10개의 데이터를 생략하고 11번째 데이터부터 가져온다.
await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
findById()
함수는 다음과 같은 파라미터로 구성되어 있다.
// 주어진 id 값에 해당하는 문서 한 건을 가져온다.
await MyModel.findById(id).exec();
// 쿼리 결과를 콜백 함수로 전달
MyModel.findById(id, (err, doc) => {});
// 쿼리를 실행하고 name, email 필드만 가져온다.
await MyModel.findById(id, 'name email').exec();
findOne()
함수는 finde()
함수와 사용하는 방법이 동일하며, 하나의 문서만을 결과로 반환한다. 다음과 같은 파라미터로 구성되어 있다.
// name이 john인 문서 한 건만 반환
await MyModel.findOne({ name: 'john' }).exec();
// 쿼리 실행 결과를 콜백 함수로 전달
MyModel.findOne({ name: 'john' }, (err, doc) => {});
// 쿼리를 실행하고 name, email 필드만 가져온다.
await MyModel.findOne({ name: 'john' }, 'name email').exec();
create()
함수를 사용해서 추가한다. customers 컬렉션에 새로운 문서를 하나 추가할 때는 create()
함수에 자바스크립트 Object로 문서 데이터를 전달하면 된다.// controllers/todo.controller.js
const createTodo = async (req, res) => {
try {
const { task, importance } = req.body;
await TodoModel.create({
task,
importance,
});
return res.status(200).json({
status: "success",
message: "새로운 todo 등록 성공",
});
} catch (error) {
res.status(500).json({
status: "error",
message: "Error creating todos",
error: {
code: 500,
message: "Internal Server Error",
error,
},
});
}
};
module.exports = { createTodo };
create()
함수에 배열로 자바스크립트 Object를 전달하면 된다.await MyModel.create([{...}, {...}])
findByIdAndUpdate()
함수는 문서의 _id
값으로 조회된 결과에 해당하는 문서를 수정한다. 다음과 같은 파라미터로 구성되어 있다.
// controllers/todo.controller.js
const editTodo = async (req, res) => {
try {
const { id } = req.params;
const { task, importance } = req.body;
await TodoModel.findByIdAndUpdate(id, {
task,
importance,
});
return res.status(200).json({
status: "success",
message: "todo 수정 성공",
});
} catch (error) {
res.status(500).json({
status: "error",
message: "Error editing todos",
error: {
code: 500,
message: "Internal Server Error",
error,
},
});
}
};
module.exports = { editTodo };
updateMany()
함수는 조회된 모든 문서를 수정한다. 다음과 같은 파라미터로 구성되어 있다.
await MyModel.updateMany({ name: /Jeremy/ }, { phone: '010-7777-5555' });
updateOne()
함수는 조회된 결과 중 첫 번째 문서를 수정한다. 다음과 같은 파라미터로 구성되어 있다.
await MyModel.updateOne({ name: 'Jeremy Go' }, { phone: '010-7777-5555' });
Model.findByIdAndDelete()
함수는 요청으로 받은 params의 id값에 해당하는 문서를 찾고 삭제한다. 그리고 삭제된 문서를 반환한다.
// controllers/todo.controller.js
const deleteTodo = async (req, res) => {
try {
const { id } = req.params;
await TodoModel.findByIdAndDelete(id);
return res.status(200).json({
status: "success",
message: "todo 삭제 성공",
});
} catch (error) {
res.status(500).json({
status: "error",
message: "Error removing todos",
error: {
code: 500,
message: "Internal Server Error",
error,
},
});
}
};
module.exports = router;
deleteMany()
함수는 조건에 해당하는 모든 문서를 삭제한다. 다음과 같은 파라미터로 구성되어 있다.
// name에 'Jeremy'가 포함된 모든 문서 삭제
await MyModel.deleteMany({ name: /Jeremy/ });
deleteOne()
함수는 조회된 결과 중 첫 번째 문서를 삭제한다. 다음과 같은 파라미터로 구성되어 있다.
// name에 'Jeremy Go'가 포함된 문서 중 첫 번째 문서 삭제
await MyModel.deleteOne({ name: 'Jeremy Go' });