ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 12장 mongoose(몽구스) 를 이용한 스키마 확장
    MeanStack (deprecated) 2016. 6. 19. 22:19



    이번 장에서는 Mongoose 로 만든 모델을 확장 시켜 보겠다. 


    이전 장에서 만든 모델에 생성날짜 속성를 추가하고 싶으며 , 거기다 생성날짜는 데이터가 생성될 때 기존 


    RDBMS 처럼 현재 시간으로 default 값을 주고 싶다면 어떻게 해야 할까?


    이를 구현 하기 위해 이전에 만든 모델을 변경하자. 


    app/models 폴더로 가서 user.server.model.js 파일의 코드를 바꿔보자. 



    var mongoose = require('mongoose'),
        Schema = mongoose.Schema;
    
    var UserSchema = new Schema({
        username : String ,
        userid : String ,
        password : String ,
        email : String ,
        created : {                   // 추가 
            type : Date,
            default : Date.now
        }                             // 추가 끝
    });
    
    mongoose.model('User',UserSchema);
    
    


    created 라는 속성을 추가하였고 내부적으로 또다시 속성을 정의하고 default 값으로 어떤 값을 줄 지 정하였다.


    코드만 봐도 설명이 필요없이 어떤식으로 되었는지 알 것 이다.


    자 여기서 의문.  그렇다면 기존에 생성된 데이터들은 이 새로운 created 라는 속성을 어떻게 처리 할 것인가? 


    놀랍게도 기존의 데이터는 해당 데이터를 질의하는 시점에 자동으로 created 속성이 생기면서 default 값으로 


    현재 날짜가 자동으로 들어 갈 것이다. 



    이제 테스트를 해보자. mongodb 를 켜고 node 서버를 킨 뒤 새로운 유저를 삽입 해보자. 







    post 로 새로운 데이터를 넣었고 응답으로 들어간 데이터를 받았을 시 created 라는 속성이 자동으로 생성되었고


    현재 시간이 default 값으로 들어 간 것이 보일 것 이다. 



    이번엔 데이터가 들어올 때 미리 정의해놓은 방식으로 들어오도록 만들어보자. 


    예제로  userid속성에 trim 옵션을 넣어보자.  넣는법은 위와 똑같다. 



    app/models 폴더로 가서 user.server.model.js 파일의 코드를 수정하자. 


    var mongoose = require('mongoose'),
        Schema = mongoose.Schema;
    
    var UserSchema = new Schema({
        username : String ,
        userid :  {                 // 변경
            type : String ,
            trim : true
        },                          // 변경 끝
        password : String ,
        email : String ,
        created : {
            type : Date,
            default : Date.now
        }
    });
    
    mongoose.model('User',UserSchema);
    
    


    userid 에 String Type 을 정의하고 trim : true 로 trim 옵션을 주었다. 


    이렇게 해두면 userid 가 들어갈 때 자동으로 앞 뒤 공백을 없애 줄 것이다. 


    이번엔 모델에 website 라는 속성이 추가 되었다고 보자. website 필드에는 http:// 또는 https:// 가


    붙어야 하는데 이를 사용자가 임의로 넣기 보다는 데이터가 들어갈 때 만약 http:// 와 https:// 가 없을


    경우 자동으로 붙어서 데이터가 들어가도록 설정을 해보자. 


    app/models 폴더로 가서 user.server.model.js 파일의 코드를 수정하자. 



     website : {                      // 추가
            type : String ,
            set : function(url) {
                if(!url) {
                    return url;
                } else {
                    if (url.indexOf('http://') !== 0 && url.indexOf('https://') !== 0) {
                        url = 'http://' + url;
                    }
    
                    return url;
                }
            }
        }                                // 추가 끝
    
    



    created 속성 뒤에 위와 같은 website 필드를 추가하자.   


    코드를 살펴보면 type 로 String 주고 set 옵션으로 url 을 인수로 받는 함수를 정의하였는데 , 여기서 url 항목이


    없다면 그냥 넘어가고 만약 url 인수가 존재한다면 (사용자가 website 항목을 적었다면) http:// 와 https:// 가 


    있는지 확인하고 없다면 http:// 를 제일 앞에 붙이게 될 것 이다. 


    그럼 여기서 기존에 website 속성이 없는 데이터들은 어떻게 되는가? 물론 기존 데이터 질의시점에 자동으로 


    website 필드가 생성되지만 , 데이터가 많이 쌓여있다면 모든 도큐먼트 데이터에 website 속성을 갱신하며 추가 


    하게 되는데 이는 심각한 성능저하가 생길 수 있다. 


    이를 방지하기 위해 기존 설정을 set 으로 변경하는 것 보단 get 방식으로 website 속성을 기존 데이터를 질의하는


    시점에 강제적으로 website 필드를 붙여서 결과가 나오도록 하는 방법이 효율적이다.


    app/models 폴더로 가서 user.server.model.js 파일의 코드를 수정하자. 



        website : {                      // 추가
            type : String ,
            get : function(url) {
                if(!url) {
                    return url;
                } else {
                    if (url.indexOf('http://') !== 0 && url.indexOf('https://') !== 0) {
                        url = 'http://' + url;
                    }
    
                    return url;
                }
            }
        }                                // 추가 끝
    });
    
    UserSchema.set('toJSON',{ getters : true });              // 추가
    mongoose.model('User',UserSchema);
    
    


    여기서는 set 을 get 으로 바꾸고  UserSchema.set('toJSON',{ getters : true });  추가했다. 


    get 으로 바꾸면 website 가 존재하는 데이터는 website 를 포함해서 나오고, 아니라면 website 필드가 나오지


    않는다. 






    위와 같이 website 가 포함된 데이터와 포함되지 않은 데이터가 같이 나오게 된다. 


    UserSchema.set('toJSON',{ getters : true });  은 res.json() 을 사용하여 다큐먼트 데이터를 출력 할 때 


    get 옵션으로 정의한 값이 JSON에 포함되게 할 것이다. 위 코드를 적지 않으면 JSON으로 데이터를 표현할 


    때 get 옵션을 무시하게 될 것 이다.



    다음으로 가상 속성을 추가 해보자. 


    예를 들어 id와 password 를 합친 필드가 출력 시 나오게 하고 싶다면 virtual() 메소드를 사용하면 된다. 


    한번 추가해보자. 


    app/models 폴더로 가서 user.server.model.js 파일의 코드를 수정하자. 


    UserSchema.virtual('idpass').get(function() {     // 추가
        return this.userid + ' ' + this.password;
    });                                           // 추가 끝
    
    
    UserSchema.set('toJSON',{ getters : true , virtuals : true});
    mongoose.model('User',UserSchema);
    


    UserSchema 에 virtual() 메소드로 idpass 라는 이름의 새로운 필드를 지정하고 userid 와 password 를 합쳤다. 


    주의 할 것은 UserSchema 의 set 옵션에 virtuals 옵션을 true 로 설정해야 virtual 메소드가 정상적으로 작동한다.




    이번 장에서는 몽구스를 이용하여 새로운 옵션을 넣는 방법을 알아 보았다. 


    다음 장에는 이 모델에 index 를 넣어 질의를 조금 더 빠르게 하는 방법과 데이터를 넣을 때 각 필드에 관해서 


    검증하는 옵션을 만들어 본다. 



    (끝) 





    (현재 폴더구조)


    댓글