처음 구성한 스키마대로 서비스가 운영되면 정말 좋겠지만, 서비스의 확장과 같은 이유로 스키마를 수정해나가야하는 경우가 생긴다.
글만 작성할 수 있었던 서비스에 댓글과 조회수 기능을 추가하려고 한다. MongoDB는 NoSQL으로 언제든지 스키마의 확장이 가능하다. 이 글에서는 스키마를 어떻게 확장하는지에 대해 작성해보았다.
1. 현재 DB는 어떤 상태인가?
Mongo Shell을 실행시켜보자.
$ mongo
현재 나의 db list와 collection list를 확인해보자. 현재 내 DB의 이름은 post이며 collections의 이름은 posts이다.
> show dbs
post 0.000GB
> use post
switched to db post
> show collections
posts
현재 document는 다음과 같이 구성되어있다.
여기서 _id, title, author ...은 key이고 오른쪽에 있는 값들은 key의 type이다.
그렇다면, posts collection의 document list를 확인해보자. pretty()를 붙여주면 예쁘게 값을 보여준다.
# db.COLLECTION_NAME.find()
> db.posts.find().pretty()
{
"_id" : ObjectId("5e7cb758875957a5eb18985f"),
"title" : "Hi MongoDB",
"author" : "seohyun",
"content" : "Welcome!",
"createdAt" : ISODate("2020-03-26T14:08:24.744Z"),
"updatedAt" : ISODate("2020-03-26T14:08:24.744Z"),
"__v" : 0
}
참고로, mongoose (Object Relational Mapper 라이브러리) 를 사용하고 있는데, __v는 versionKey를 뜯하며, mongoose에 의해 생성된 값이며 default 값은 0이다. versioning 관련해서는 다음에 글을 작성해보도록 하겠다. versioning Docs
Mongoose v5.9.6: Schemas
Schemas If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. If you are migrating from 4.x to 5.x please take a moment to read the migration guide. Everything in Mongoose starts with a Schema. Each s
mongoosejs.com
2. 어떻게 추가할 것인가? Mongo Shell을 이용해보자
변경하고자하는 Document 구조는 다음과 같다. viewNum과 comments가 추가되었다. 하나의 글에는 여러 개의 댓글이 달릴 수 있으므로, One-to-Many Relationship이다. 이때, Embedded Document pattern을 사용할 수 있다. 새로운 collection의 구조는 아래와 같다.
이미 존재하는 레코드는 viewNum과 comments field가 없는데 어떻게 해야할까? mongo Shell에 아래 명령어를 입력해보자.
2-1. viewNum field 추가하기
먼저, viewNum부터 추가해보자.
# db.COLLECTION_NAME.updateMany({<filter>}, {<update>})
> db.posts.updateMany({}, { $set: { "viewNum": NumberInt(0) } })
1. updateMany
만약 정말 많은 양의 레코드가 존재한다면, 하나씩 업데이트를 하기엔 너무나도 많은 시간이 걸린다. updateMany를 활용하여 여러 개의 레코드를 바꿔보자
2. <filter>
filter option을 통해서 특정 레코드만 업데이트할 수 있다.
# 모든 레코드 변경
{}
# filter를 통해 특정 레코드만 변경
{ "author" : "seohyun" }
3. NumberInt(0)와 0의 차이
그냥 0을 넣게 될 경우, data type이 Double로 설정된다. viewNum은 int형이 알맞으므로, NumberInt를 통해 Int형으로 바꿔주자.
# double형
> db.posts.updateMany({}, { $set: { "viewNum": 0 } })
# int형
> db.posts.updateMany({}, { $set: { "viewNum": NumberInt(0) } })
4. 결과값 보기
위의 명령어를 실행하면, 아래와 같은 결과를 보여준다.
/* 1 */
{
"acknowledged" : true,
"matchedCount" : 10.0,
"modifiedCount" : 10.0
}
acknowledged: wrtie operation이 성공적으로 수행되었는지 알려주는 값
matchedCount: 쿼리문에 해당하는 레코드 수
modifiedCount: 수정된 레코드 수
5. 수정되었는지 확인해보기
# db.COLLECTION_NAME.find()
> db.posts.find().pretty()
...
{
"_id" : ObjectId("5e7cb758875957a5eb18985f"),
"title" : "Hi MongoDB",
"author" : "seohyun",
"content" : "Welcome!",
"createdAt" : ISODate("2020-03-26T14:08:24.744Z"),
"updatedAt" : ISODate("2020-03-26T14:08:24.744Z"),
"__v" : 0,
"viewNum" : 0
}
viewNum값이 0으로 들어간 것을 확인할 수 있다.
2-2. comment field 추가하기
하나의 post에는 여러개의 comment가 존재할 수 있기 때문에 array형을 사용해야한다.
# db.COLLECTION_NAME.updateMany({<filter>}, {<update>})
db.posts.updateMany({}, { $set: { "comments": [{ "comment_id": new ObjectId(), "comment_author": "seohyun", "comment_text": "hello", "comment_createdAt": new Date() }] } })
# 가독성을 위한 indentation
db.posts.updateMany(
{},
{ $set:
{ "comments":
[{
"comment_id": new ObjectId(),
"comment_author": "seohyun",
"comment_text": "hello",
"comment_createdAt": new Date()
}]
}
}
)
comment_id: new ObjectId()를 통해 자동으로 mongodb가 id를 생성해준다.
comment_createdAt: new Date()를 통해 자동으로 현재 시간을 넣어준다.
수정되었는지 확인해보자.
# db.COLLECTION_NAME.find()
> db.posts.find().pretty()
...
{
"_id" : ObjectId("5e7cb758875957a5eb18985f"),
"title" : "Hi MongoDB",
"author" : "seohyun",
"content" : "Welcome!",
"createdAt" : ISODate("2020-03-26T14:08:24.744Z"),
"updatedAt" : ISODate("2020-03-26T14:08:24.744Z"),
"__v" : 0,
"viewNum" : 0,
"comments" : [
{
"comment_id" : ObjectId("5e7d6411fdb642d18789d55f"),
"comment_author" : "seohyun",
"comment_text" : "hello",
"comment_createdAt" : ISODate("2020-03-27T11:25:21.116+09:00")
}
]
}
의도한대로 만들어진 것을 확인할 수 있다.
다음 글에서는 mongo shell이 아닌 mongoose에서는 어떻게 스키마를 확장하는지 작성해보려고 한다.
'Programming > Database & Docker' 카테고리의 다른 글
MongoDB Replica Set 구성하기 - Docker Swarm (1) | 2023.06.04 |
---|---|
Angular + Nginx 도커라이징 (0) | 2020.04.28 |
Node.js 웹 앱의 도커라이징 (0) | 2020.04.28 |
[MongoDB] Mac OS X에서 MongoDB 시작하기 (0) | 2020.03.16 |