Udemy <The Web Developer 부트캠프 2024>
new mongoose.Schema()
에 다양한 스키마 유효성 설정을 추가할 수 있다.- 필드명 후
: { }
객체 안에 값을 넣으면 되는데, 굉장히 다양한 속성들이 제공된다. required
를true
로 설정하면 해당 필드를 필수 필드로 요구할 수 있다.default
옵션에 값을 전달하면 해당 필드에 대한 값이 없을 경우 자동으로 사전에 정의해둔 초기화 값이 들어가도록 할 수 있다.- 필드의 값이 참조형, 예를 들어 배열일 경우,
[String]
과 같은 형식으로 정의하면 문자열 형태의 값들을 포함하는 배열임을 나타낼 수 있다. - 필드의 값이 참조형, 예를 들어 객체일 경우, 필요한 필드와 그에 대한 속성을 중첩된 형태로 넣어줄 수 있다. 예를 들어,
qty: { online: { type: Number, default: 0 }, {inStroe: { type: Number, default: 0 }}
과 같은 식이다. - mongoose는 처음 값이 추가될 땐
mongoose.Schema
에 정의해 둔 유효성 조건들을 확인하여 검사를 실행해주지만, 값을 업데이트할 땐 기본적으로 미리 설정해 둔 유효성 검사를 실행해주는 조건이false
로 설정돼있다. 만약에 값을 수정해서 넣을 때에도Schema
에 따른 유효성 검증을 동일하게 실행해주고 싶다면Product.findOneAndUpdate({ name: 'Tire Pump' }, { price: -19.99 }, { new: true, runValidators: true })
처럼runValidators
라는 옵션을 켜줘야한다. - 참고로
name: Tire Pump
는 원하는 도큐먼트를 찾기 위한 조건이고,price: -19.99
는 변경할 필드와 값익,new: true
는 업데이트 이후 Promise 객체의 resolve 데이터로 새롭게 수정된 데이터를 내려주는 옵션이다.findOneAndUpdate
처럼 값을 처리해주는 옵션들의 마지막 매개 변수는 보통 옵션을 전달하는 용도로 사용되기 때문에, 마지막 매개 변수에 객체로{ runValidators: true }
설정을 가급적 추가해주자. Schema
에enum
이라는 유효성 검증 속성이 있다.enum
의 값으로는 배열을 전달하며, 값이 사전에 정의한 배열 안에 있는 값이 아니면 에러를 뱉는다. 예를 들어,{ size: { enum: ['S', 'M', 'L'] }}
로 정의가 됐다면size
에XS
이나XL
이 값으로 들어왔을 때 에러를 뱉는다.- 자바스크립트에서 클래스, 생성자 함수에 인스턴스 메서드와 정적 메서드를 정의할 수 있는 것처럼, mongoose의 모델을 사용하면 도큐먼트 생성 시 적용할 인스턴스-정적 메서드를 정의할 수 있다.
- 인스턴스 메서드는 유효성을 정의한
mongoose.Schema
에 추가해주면 된다. 예를 들어,productSchema.methods
에 점 표기법으로 메서드를productSchema.methods.toggleOnSale
처럼 추가해주면 해당 스키마가 적용된 모든 도큐먼트에서 사용이 가능하다. - 아래는 인스턴스 메서드를 사용해
onSale
토글 이벤트 처리, 카테고리 추가 등 이벤트를 처리해준 예시이다.
/* products 콜렉션의 도큐먼트들에 적용되는 인스턴스 메서드: onSale 토글 메서드 */ productSchema.methods.toggleOnSale = function () { this.onSale = !this.onSale; return this.save(); }; /* products 콜렉션의 도큐먼트들에 적용되는 인스턴스 메서드: 카테고리 추가 메서드 */ productSchema.methods.addCategory = function (newCat) { this.categories.push(newCat); return this.save(); }; const Product = mongoose.model('Product', productSchema); const findProduct = async () => { const foundProduct = await Product.findOne({ name: 'Tire Pump' }); console.log(foundProduct); await foundProduct.toggleOnSale(); console.log(foundProduct); await foundProduct.addCategory('Outdoors'); console.log(foundProduct); }; findProduct();
- 인스턴스 메서드에서 메서드를 호출하는 도큐먼트 자기 자신을 가리키기 위해
this
를 사용하는 경우가 생긴다. 이를 위해 화살표 함수보단 일반 함수로 인스턴스 메서드르 정의하는 게 권장된다. 화살표 함수는this
를 가지지 않고, 상위의this
를 참조하기 때문에, 화살표 함수로 인스턴스 생성 시this
참조에서 의도치 않은 동작이 발생할 수 있기 때문이다. - 정적 메서드는
productSchema.statics
과 같이mongoose.Schema
로 생성한 스키마의statics
메서드를 사용해 정의한다.productSchema.statics.fireSale = function () { return this.updateMany({}, { onSale: true, price: 0 })};
와 같이 정의하면productSchema
를 사용해 생성한 모든Product
모델에서 사용 가능하며, 호출 시Product
모델로 생성한 모든 인스턴스(도큐먼트)들에서onSale
은true
로,price
는0
으로 변경된다. - Mongoose는 Virtual mongoose라는 것을 제공한다. 실제로 데이터베이스에 저장될 필요는 없지만 활용하면 좋은 값이 있을 때 가상의 mongoose로 정의해 값을 사용할 수 있다.
- 예를 들어,
personSchema
를 생성해first: String, last: String'
으로 필드 속성을 지정해준 다음,personSchema
.virtual('fullName')이라고 정의해 가상의 필드를 설정해줄 수 있다.
fullName`은 실제 mongoDB 콜렉션-도큐먼트에 추가되진 않지만, 변수처럼 해당 값에 접근해 사용할 수 있다. - 가상 mongoose에는 getter와 setter 함수로 접근 가능하다. 아래와 같은 방식으로 사용한다.
const personSchema = new mongoose.Schema({ first: { type: String, }, last: { type: String, }, }); personSchema .virtual('fullName') .get(function () { return `${this.first} ${this.last}`; }) .set(function (v) { [this.first, this.last] = v.split(' '); });
fullName
이라는 필드는 도큐먼트에 실제로 추가되진 않는다. 하지만,fullName
의 setter 메서드로 추가된 값이 있다면first
와last
필드의 값이 실제로 바뀌긴 한다. 실제 DB에 값이 저장되진 않지만, DB의 값을 조작하는 데 활용은 되고 있는 것이다.- mongoose를 활용한 특정 작업을 실행하기 전, 또는 후에 원하는 로직을 실행할 수 있도록 미들웨어 설정을 할 수 있다.
- 작업 수행 전 실행을 원하면
pre
, 이후에 실행을 희망하면post
를 설정하면 된다. personSchema.pre()
,personSchema.post()
형태로 사용하며, 첫 번째 매개변수론 어떠한 작업의 전-후에 실행할지를 나타내는 문자열(e.g.'save'
), 두 번째 매개변수론 실제 전-후에 실행할 작업을 콜백 함수 형태로 전달한다.
'TIL' 카테고리의 다른 글
250101 (0) | 2025.01.01 |
---|---|
241230 TIL (0) | 2024.12.30 |
241223 TIL (0) | 2024.12.25 |
241222 TIL (0) | 2024.12.23 |
241221 TIL (0) | 2024.12.21 |