앞서 mongoose의 Model에 대해서 공부를 했을 때 간략하게 Document에 대해서 설명을 했었다. 이번에는 Documents가 Model과 어떤 차이점이 있는지 그리고 여기에는 어떤 함수가 있는지 알아보고자 한다.
Models를 통해 생성되는 인스턴스를 Documents라고 부르기에 Models > Documents로 Documents는 Models의 하위 개념이다. 따라서, 모델을 먼저 만들고 Documents를 만들어야 한다.
const MyModel = mongoose.model('Test', new Schema({name: String}));
const doc = new MyModel();
doc instanceof MyModel; // true
doc instanceof mongoose.Model; // true
doc instanceof mongoose.Document; // true
우리가 MongoDB를 조회할 때 Documents를 가져오게 되는데 쿼리문을 이용한다.
const doc = await MyModel.findOne();
doc instanceof MyModel; // true
doc instanceof mongoose.Model; // true
doc instanceof mongoose.Document; // true
예시) 단순히 업데이트를 할 경우
doc.name = 'foo';
await doc.save();
or
doc.save().then(savedDoc => {
savedDoc === doc; // true
})
예시) Documents 삭제 후 업데이트 시 오류가 발생
const doc = await MyModel.findOne();
await MyModel.deleteOne({_id: doc._id});
doc.name = 'foo';
await doc.save();
단순히 save()를 통해서 업데이틀 할 수 있지만, 유연하게 업데이트를 위해서는 쿼리문을 통해서 업데이트를 진행할 수 있다.
await MyModl.updateMany({}, {$set: {name: 'foo'}});
Documents를 업데이트 하는 과정에서 타입이 맞는지, 조건에 맞는지 확인해야 되는 Validation 과정을 거쳐야 한다. validate()
함수를 사용해 우리는 유효화 작업을 진행한다.
예시) 기본 확인 과정
const schema = new Schema({name: String, age: {type: Number, min: 0}});
const Person = mongoose.model('Person', schema);
let p = new Person({name: 'foo', age: 'bar'});
await p.validate();
let p2 = new Person({name: 'foo', age: -1});
await p2.validate();
첫 번재 경우에는 age의 타입이 맞지 않아 오류가 발생하고 두번째 경우에는 최소 조건이 맞지 않아 오류가 발생한다.
예시) 쿼리를 통해 한번에 확인
await Person.updateOne({}. {age: 'bar'});
await Person.updateOne({}, {age: -1}, {runValidators: true});
위와 마찬가지로 같은 오류가 발생한다.
Documents를 덮어쓰는 방법에는 2가지가 있다. 하나는 Document#overwrite()
이고 다른 하나는 save()
와 연관된 함수를 사용하는 것이다.
const doc = await Person.findOne({_id});
doc.overwrite({name: 'Jean-Luc Picard'});
await doc.save();
await Person.replaceOne({_id}, {name: 'Jean-Luc Picard'});
Subdocument는 말그대로 Document 안에 다른 Document를 넣어서 여러 계층의 스키마를 생성하는 것을 의미한다.
const Parent = mongoose.model('Parent', parentSchema);
const parent = new Parent({children: [{name: 'Matt'}, {name: 'Sarah'}]})
parent.children[0].name = 'Matthew';
parent.save(callback);
기본적으로 미들웨어를 쓰기도 하고 커스텀 유효화 작업으로 안쪽 스키마를 다룬다. 더 자세한 Subdocument를 알고 싶다면 아래의 링크를 보면서 공부하면 될 것 같다.