-
2023 - 06 - 17 MongoDB, Mongoose, 몽구스, Schema 스키마, model, populate, Queries 쿼리Today I Learned/TIL 06 2023. 6. 17. 11:33
NoSQL 데이터베이스로 분류되는 MongoDB는 가장 유명한 NoSQL데이터베이스 시스템이다.
Mongoose
Mongoose는 Node.js와 MongoDB를 연결해주는 ODM이다.
**ODM(Object Document Mapping) : 객체와 문서를 1대1로 매칭하는 역할
MongoDB의 ODM은 다양하지만 Mongoose가 가장 유명하다.
패키지 설치
npm install mongoose --save yarn add mongoose
위와 같이 노드 패키지 매니저 npm 혹은 yarn을 통해 설치할 수 있다.
MongoDB 연결하기 (둘중 하나)
1) require을 이용하는 방법
const mongoose = require('mongoose'); mongoose.connect("mongodb://lodcallhost/<db이름>", {useNewUrlParser: true});
2) import를 이용하는 방법
import mongoose from 'mongoose'; mongoose.connect('mongodb://localhost/<db이름>', {useNewUrlParser: true});
우선 mongoose 모듈을 require(혹은 import)해준다. 그 이후 connect 메소드를 통해 MongoDB에 연결한다.
connect 메소드의 인자로는 mongdodb url(기본적으로는 localhost를 사용.) 과 useNewUrlParser와 같이 error발생하지 않도록 다른 인자들을 객체 형식으로 선언한다.
만약 본인만의 mongoDB 서버가 있으면, url인자에 'mongodb://username:password@host:port/database' 를 보내면 된다.
Schema 생성하기
Mongoose는 Schema라는 개념이 존재한다. MongoDB의 경우 Document에 데이터를 아무거나 막 넣어도 에러가 발생하지 않는다. 이는 양날의 검과 같은데, 데이터를 막 넣을 수 있기에 편리하지만 반대로 불필요한 데이터 같은 데이터도 다 들어가며, 어떤 경우엔 원하는 자료형과 맞지 않는 데이터가 들어갈 수도 있는 문제가 있다.
그래서 Mongoose는 Schema를 도입한 것. 스키마는 SQL의 table과 비슷한 개념이다. 데이터를 넣을 때 schema에서 선언한 틀에 맞게 데이터를 넣을 수 있도록 해준다.
import mongoose from 'mongoose'; const imageSchema = new mongoose.Schema({ width : Number, height : Number, }); const developersSchema = new mongoose.Schema({ name : {type : String, required: true}, age : {type : Number, required: true}, image : imageSchema, nickname : String, language : String, friends : [String], });
스키마는 위와 같이 mongoose를 import 한 뒤, new mongoose.Schema({});를 통해 생성 가능
필드를 하나씩 살펴보면
name은 String타입이며, required : true를 통해 꼭 필요한 값으로 지정.
age는 Number타입이며, 이 또한 required : true를 통해 필요한 값으로 지정.
image필드는 다른 필드와 조금 다르게 선언되었는데, imageSchema라고 지정되어있다.
이는 image필드는 imageSchema라는 또 다른 스키마를 타입으로 가진다.
풀어서 보면
image : { width : Number,
height : Number,
}
nickname은 String타입으로 선언되었다. (language도 동일!)
friends는 String타입의 배열로 선언되었다.
스키마를 만든뒤 데이터베이스 서버로 쏙 넣어준다import mongoose from 'mongoose'; const imageSchema = new mongoose.Schema({ width : Number, height : Number, }); const developersSchema = new mongoose.Schema({ name : {type : String, required: true}, age : {type : Number, required: true}, image : imageSchema, nickname : String, language : String, friends : [String], }); const model = mongoose.model('Developer',developerSchema);
데이터베이스 서버로 넣어주기 위해서는 구현해놓은 schema를 model 메소드를 통해 객체로 만들어주어야 한다.
따라서 model이라는 객체를 생성한 뒤, 그 객체에 스키마 model을 넣어준다.
이후 각자 원하는 서버에 올리면 됨.
Populate 사용하기
MongoDB 스키마를 만들다 보면, 필드 내에 다른 다큐먼트의 ObjectID를 쓰는 경우가 있다.
const mongoose = require('mongoose'); const Schema = mongoose.Schema; const personSchema = Schema({ _id: Schema.Types.ObjectId, name: String, age: Number, stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }] }); const storySchema = Schema({ author: { type: Schema.Types.ObjectId, ref: 'Person' }, title: String, fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }] });
출처 : https://mongoosejs.com/docs/populate.html
위의 _id와 stories를 보면 타입으로 Schema.Types.ObjectId가 지정되어있다.
MongoDB에서는 데이터가 차곡차곡 쌓일 때, 그 데이터 하나하나를 document라고 한다.
_id와 stories는 그 document를 가리키는 타입인 것.
{ _id: {$oid : 5a23c1b5d52a003c98e13f1c}, name: 'CharmSae', age: 16, stories : {$oid :5a23c1b5d52a003c98e13f1b}, }
이런 형식으로 데이터가 조회되고, _id와 stories에 document id값이 저장이 되어있다.
Populate는 간단하게 말해서 이런 id값을 펼쳐서 보여주는 기능
사용과 그에 따른 결과는 다음과 같다.Person.findOne({ name: 'charmsae' }).populate('stories').exec((err, data) => { console.log(data); }); { _id: {$oid :5a23c1b5d52a003c98e13f1c}, name: 'CharmSae', age: 16, stories : { author : {$oid :5a23c1b5d52a003c98e13f1d}, title : 'HueMoneLabStory' fans : {$oid :5a23c1b5d52a003c98e13f1d}, }, }
위의 결과랑은 다르게 stories에 어떠한 document가 출력이 되었다,
이렇게 populate를 활용하면 Schema.Types.ObjectId가 참조하는 다른 document를 조회할 수 있다
하지만 populate를 남발하는 것은 좋지 않다. populate는 $oid값을 조회한 뒤 자바스크립트에서 합쳐주는 것이지 DB 자체에서는 합쳐지지 않기에 성능이 좋은 편은 아니기 때문
Queries
데이터를 조회하는 방식인 Query
Mongoose에는 다양한 Query가 존재하는데 그중 대표적인 것들만 정리했다.더 자세한 Query는 mongoose 공식 사이트를 참고 https://mongoosejs.com/docs/queries.html
findOne()
const query = Person.findOne({name : 'charmsae'}); //Person이라는 컬렉션 안에서 name이 charmsae인 documents를 '하나'불러옵니다.
find()
const query = Person.find({name : 'charmsae'}); //Person이라는 컬렉션 안에서 name이 charmsae인 documents를 '모두' 불러옵니다.
deleteOne()const query = Person.deleteOne({name : 'charmsae'}); //Person이라는 컬렉션 안에서 name이 charmsae인 documents를 '하나' 삭제합니다.
deleteMany()
const query = Person.deleteMany({name : 'charmsae'}); //Person이라는 컬렉션 안에서 name이 charmsae인 documents를 '모두' 삭제합니다.
이때, One이 들어간 쿼리문은 가장 처음 조회되는 document를 불러온다.
sort()const query = Person.find({name : 'charmsae'}).sort(age : -1); //Person이라는 컬렉션 안에서 name이 charmsae인 모든 document를 age순으로 정렬합니다. //이때, age : 1이면 오름차순, age : -1이면 내림차순으로 정렬합니다.
select()const query = Person.findeOne({name : 'charmsae'}).select('age'); //Person이라는 컬렉션 안에서 name이 charmsae인 documents를 '하나' 조회한 뒤, // age 필드만 가져옵니다.
MongoDB, Mongoose 아이디 비밀번호 설정
일명령 프롬프트에서 mongod라고 입력한다.
에러가 발생하거나 없다고 뜨시면, mongodb를 먼저 설치하기. (몽고디비 공식사이트)
위와 같이 뜨면 성공
그 뒤에는 명령 프롬포트를 하나 더 띄운 뒤 mongo라고 쓴다위와 같이 뜨시면 이제 준비완료, 아래와 같이 작성한다.
use admin db.createUser({ user: '이름', pwd: '비밀번호', roles: [{role : "userAdminAnyDatabase"}] })
그런 뒤, 다시 mongoose파일로 가서
const mongoose = require('mongoose'); mongoose.connect("mongodb://lodcallhost/<db이름>", {useNewUrlParser: true});
와 같이 작성한 코드를 다음과 같이 수정한다
const mongoose = require('mongoose'); mongoose.connect('mongodb://아이디:비밀번호@호스트:포트/dbname'), {useNewUrlParser: true});
'Today I Learned > TIL 06' 카테고리의 다른 글
2023 - 06 - 19 쿠키 (Cookie)와 세션 (Session) (0) 2023.06.19 2023 - 06 - 18 프론트엔드와 백엔드 (0) 2023.06.18 2023 - 06 - 16 HTTP와 웹 서버 & 패키지매니저 (Package Manager) (0) 2023.06.16 2023 - 06 - 15 클래스 Class, 생성자 Constructor, this와 프로퍼티 (property), 인스턴스, 부모클래스 자식클래스 상속 (1) 2023.06.15 2023 - 06 - 14 에러핸들링 (Error Handling) try catch, throw, finally (0) 2023.06.14