mongoose에 대하여

cozups·2022년 5월 20일
0

Mongoose?

Node.js와 MongoDB를 위한 ODM (Object Data Mapping)

호환성이 없는 Javascript Object와 MongoDB 데이터를 매핑하여 CRUD가 가능하게 한다.

Connection

app.js 파일에서

const mongoose = require('mongoose');

...

// CONNECT TO MONGODB SERVER
mongoose
  .connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log('Successfully connected to mongodb'))
  .catch(e => console.error(e));

mongoose를 가져와서 mongoDB에 연결하는 코드이다.

Schema

Schema는 데이터베이스를 구성하는 레코드의 크기, 키(key)의 정의, 레코드와 레코드의 관계, 검색 방법 등을 정의한 것이다.

Mongoose의 Schema는 MongoDB에 저장되는 document의 Data 구조 즉 필드 타입에 관한 정보를 JSON 형태로 정의한 것으로 RDBMS의 테이블 정의와 유사한 개념이다.

그러나 MongoDB는 NoSQL이므로 Schema-less하다.
= 고정 Schema가 존재하지 않는다.

이는 자유도가 높아서 유연한 사용이 가능하다는 장점이 있지만, 명시적인 구조가 없기 때문에 어떤 필드가 어떤 데이터 타입인지 알기 어려운 단점이 있다.
이러한 문제를 보완하기 위해서 Mongoose는 Schema를 사용한다.

const mongoose = require('mongoose');

// Define Schemes
const todoSchema = new mongoose.Schema({
  todoid: { 
  	type: Number, 
    required: true, 
    unique: true
  },
  content: { 
  	type: String, 
    required: true 
  },
  completed: { 
  	type: String, 
    default: false 
  }
},
{
  timestamps: true
});

// Create Model & Export
module.exports = mongoose.model('Todo', todoSchema);

Schema types - https://mongoosejs.com/docs/schematypes.html
timestamps - https://mongoosejs.com/docs/guide.html#timestamps

Model

model() 메소드에 문자열과 schema를 전달하여 model을 생성한다.
model은 보통 대문자로 시작한다.

const Todo = mongoose.model('Todo', todoSchema);

'Todo'라는 collection을 생성하고 todoSchema를 사용하겠다는 뜻이다.
실제 collection 이름은 'Todos'로 변환된다.

model은 생성자이므로 instance를 생성할 수 있는데 이것은 개별 document를 나타낸다.
instance 생성시 생성자에 초기값을 전달하거나 instance 생성 후 속성과 값을 추가하여 document를 생성할 수 있다.

const todo = new Todo({
  todoid: 1,
  content: 'MongoDB',
  completed: false,
  ...
});

// or

const todo = new Todo();
todo.todoid = 1;
todo.content = 'MongoDB';
todo.completed = false;
...

Methods

1. create

await Character.create({ name: 'Jean-Luc Picard' });

create 메소드를 통해 Character model에 삽입하는 코드이다.
삽입할 document를 인자로 넘긴다.
위 코드는 'Jean-Luc Picard'라는 캐릭터를 넣은 것이다.

await Character.create([{ name: 'Will Riker' }, { name: 'Geordi LaForge' }]);

여러 document를 넣을 수도 있다. 이 경우에는 array 형태로 넘겨준다.

const user = new userSchema({
  userid: userid,
  job: job,
});
const result = await user.save();

save 메소드를 통해서도 document를 넣을 수 있다.

두 방법의 차이점은,
create 메소드는 Model로부터 call하는 메소드이다. 그러나 save는 instance로부터 call하는 메소드이다.
즉, create => Model.create() 형태이고 save => instance.save() 형태라고 보면 된다.

2. find

  1. Model.find()
    메소드의 인자로 필터링할 조건을 넣으면 된다.
// find all documents
await MyModel.find({});

// find all documents named john and at least 18
await MyModel.find({ name: 'john', age: { $gte: 18 } }).exec();

// executes, passing results to callback
MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
  1. Model.findOne()
    조건에 해당하는 하나의 document만 찾는다.
// Find one adventure whose `country` is 'Croatia', otherwise `null`
await Adventure.findOne({ country: 'Croatia' }).exec();

없는 경우에는 null을 리턴한다.

  1. Model.findById()
    request의 파라미터로 넘어오는 id를 통해 document를 찾는다.
async (req, res) => {
  const { id } = req.params;
  const post = await Post.findById(id);
  return res.render("write", { pageTitle: post.title, post });
};

exec()는 뭐냐?

find, findOne, findById, findOneAndUpdate 등의 메서드의 리턴값은 Query라고 되어 있다. Mongoose Query는 프로미스가 아니고, then을 사용할 수 있는 일종의 유사 프로미스라고 할 수 있다.

find, findOne 등의 메서드 뒤에 exec()을 붙이든 안 붙이든 기능은 동일하다.

대신 exec()을 사용하면 유사 프로미스가 아닌 온전한 프로미스를 반환값으로 얻을 수 있으며, 에러가 났을 때 stack trace에 오류가 발생한 코드의 위치가 포함되기 때문에 공식 문서에서도 exec()을 사용할 것을 권장하고 있다.

3. update

  1. Model.updateOne()
    찾는 데이터 중 하나만 업데이트 한다.
User.updateOne({name: "cozups"},{age: 20});
  1. Model.updateMany()
    찾는 모든 데이터를 업데이트 한다.
User.updateMany({필터},{업데이트 할 내용});

4. delete

  1. Model.deleteOne()
    데이터 하나를 찾아서 지운다.
User.deleteOne({name: "cozups"},{age: 20});
  1. Model.deleteMany()
    찾은 모든 데이터를 지운다.
User.deleteMany({필터},{삭제 할 내용});

request에서 params, query, body의 차이점

  1. req.params
    주소에 포함된 변수를 담는다.

  2. req.query
    주소 바깥의 ? 이후의 변수를 담는다.

  3. req.body
    XML, JSON, Multi Form 등의 데이터를 담는다.

profile
이제는 더 이상 물러날 곳이 없다

0개의 댓글