목차

Database; 모델링 #2

🗓️

오늘 한 것

1. 미디어 관련 모델링 #2 (MongoDB)

// 미디어 schema
{
    mediaId: UUID(),
    media: {
        mediaPath : "uri or url string",
        mediaMetadata: {
            mediaType:"dedicate,cloud,publish",
            mediaTitle:"media title string",
            uploadDate: ObjectId.getTimestamp(),
            modifiedDate: "timedate",
            exif:{ //EXIF데이터가 들어가면 좋겠다 
            },
        }
    }
},

위와 같이 미디어 타입으로 언급된 것은 다음과 같은 고민이 있기 때문이다.

  • 미디어와 글을 같은 타입으로 볼 것인가 → 전통적인 CMS와 다르게 모든 글을 가지고 올 때 개별 사진을 같이 가지고 왔으면 좋겠다. 즉, 글이 주가되는 CMS가 아니라 사진이 주를 이루는 CMS.
  • 미디어에 캡션을 얼마나 부착할 것인가 → 가령 한장의 사진이나 유투브 영상에 담긴 스토리에 대한 reference
  • 결론적으로 미디어도 하나의 글(객체)이면 좋겠다. 아래와 같이 고쳐본다
// 미디어→객체 schema
{
    Id: UUID(), //_id를 대신해 눈에 보이는 고유 번호가 필요해 보인다. 가령 DB를 이전했다거나. 변하면 안되는 상품코드라던가.
    title:"string",
	uploadDate: ObjectId.getTimestamp(),
	modifiedDate:,
	content: {
		path: "uri or url string",
		linkedDocument: [reference1, reference2, reference3] // 일종의 컴포넌트 개념
        metadata: {
            type:"dedicate,cloud,publish",
            modifiedDate: "timedate", // OS상의 파일 스탬프를 가지고 올 수 있으면 좋겠다.
            exif:{
				//EXIF데이터가 들어가면 좋겠다.
            },
        }
    }
},

아래와 같이 linkedDocument로 따로 관리한다. 왠만하면 마크다운을 써야지.

// linkedDocument
{
	Id: UUID(),
	title: "String" //모든 단락에는 소제목이 필요하다.
	uploadDate:,
	modifiedDate:,
	content: "markdown string"
}

이렇게 되면 겹치는데 이건 내부에서 분기를 해서 구분해야할까? 아니면 따로 타입을 만드는게 맞을까?

2. MongoDB 기본 쿼리

mongo Shell

  • MongoDB에서는 mongo쉘에서 작업을 할 수 있다. 아래 기본 쿼리에 대해서 정리해봤다.
  • 시작하는 몇가지 방법
mongo
mongo --host 10.10.10.1:28015
mongod --config /usr/local/etc/mongod.conf --fork

1) insert

db.inventory.insertOne(
   { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
   { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
   { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])

  • 이렇게 삽입하면 document 마다 기본키 역할을 하는 고유한 _id 필드가 생성된다. 값은 기본적으로 ObjectId를 생성한다.

2) update

db.inventory.updateOne(
   { item: "paper" },
   {
     $set: { "size.uom": "cm", status: "P" },
     $currentDate: { lastModified: true }
   }
)
db.inventory.updateMany(
   { "qty": { $lt: 50 } },
   {
     $set: { "size.uom": "in", status: "P" },
     $currentDate: { lastModified: true }
   }

  • $set 연산자를 통해 앞의 paper 아이템을 찾아 변경한다.
  • $currentDate 연산자를 통해 lastModified 필드를 변경한다.

3) replace

db.inventory.replaceOne(
   { item: "paper" },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)

  • update와 다른점은 _id필드를 제외한 다른 필드를 전부 지우고 새로 document를 구성한다.

3) delete

db.inventory.deleteMany({})
db.inventory.deleteMany({ status : "A" })
db.inventory.deleteOne( { status: "D" } )

4) find

db.inventory.find( {} )
db.inventory.find( { item: "canvas" } )


습득한 지식

1. EAV패턴과 안티패턴 해법

  • 안티패턴이란 ‘실제로 많이 쓰이지만 가독성이나 효율은 떨어지는 코드 또는 구조’를 말한다.
  • 기존에 유연한 메타데이터 설계를 위한 key-value구조의 테이블을 따로 관리하는 것이 안티패턴이라고 한다.
  • 위 글에 서브타입 모델링 기법을 쓴다는데 이건 좀 더 시간을 갖고 찾아봐야겠다.
  • 더 볼만한 글 : ORM은 안티패턴이다

2. 전통적인 엔터티 관계

1) 1:1

2) 1:N

3) N:M


궁금한 점


다음에 진행할 내용

  • RDB의 역사
  • NoSQL이 등장한 히스토리
  • MongoDB; ObjectID
  • MongoDB; 기본 연산자
  • Hash 함수 (SHA-1, SHA-256, MD5) / 눈사태 효과