일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- AWS 요금
- AWS #CloudTrail #AWS로그
- AWS CloudTrail
- AWS Route53
- MongoDB
- 스프링 게시판
- 코드프레소
- AWS
- Loard Balancer
- SrpingBoot
- aws ec2
- MongoDB DataModel
- VPC EC2
- MongoDB 참조
- codepresso
- Datamodel
- AWS NAT
- JPA연관관계
- AWS VPC
- 레디스설치
- SpringProject
- AWS NAT gateway
- Amazon Web Service
- 소프트웨어 개발과 테스트
- codepreosso
- EC2 생성
- EC2 배포
- MongoDB Reference
- 몽고DB
- ubuntu 배포
- Today
- Total
정환타 개발노트
MongoDB Data Model(Relationship, Tree 구조) 본문
Data Model
이번에는 데이터 모델들에 대해 기술을 하겠다.
MongoDB 또한 documents간의 관계를 설정할 수 있는데, 그러한 관계를 설정할 수 있는 모델 구조는 다음과 같다.
One-to-One Relationship(일대일 관계)
두개의 document에 대해 일대일 관계로 구성할 수 있다.
아래의 예제에서는 후원자(patron)와 주소를 매핑하고 있고, 주소에는 후원자에 대한 reference가 포함된다("patron_id")
{
_id: "joe",
name: "Joe Bookreader"
}
{
patron_id: "joe",
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
}
하지만 만약 이름(name)을 가지고 주소를 검색하는 일이 많아 진다면, 해당 데이터를 조회하기 위해 여러 쿼리를 실행해야 한다.
따라서, 일대일 관계에서 더 나은 데이터 모델은 후원자 데이터에 주소가 내장되는 구조이다.
{
_id: "joe",
name: "Joe Bookreader",
address: {
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
}
}
위와 같은 데이터 모델을 사용하면, 하나의 쿼리를 통해 후원자의 전체 정보를 검색할 수 있다.
One-to-Many Relationship(일대다 관계)
이번에는 위의 예제를 활용하여 일대다 관계를 가지는 데이터 모델이다.
아래에는 후원자가 여러 주소를 가지는 관계이며, 이번에도 주소'들'은 후원자들에 대해 reference를 가지고 있다.
{
_id: "joe",
name: "Joe Bookreader"
}
{
patron_id: "joe",
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
}
{
patron_id: "joe",
street: "1 Some Other Street",
city: "Boston",
state: "MA",
zip: "12345"
}
이번에도 만약 이름을 이용한 주소 조회가 많아 진다면, 한번의 쿼리를 통해서 데이터를 가져올 수는 없다.
따라서 MongoDB에서 사용하는 일대다 모델에서도 주소를 후원자에게 내장시키는 구조를 사용한다.
{
_id: "joe",
name: "Joe Bookreader",
addresses: [
{
street: "123 Fake Street",
city: "Faketon",
state: "MA",
zip: "12345"
},
{
street: "1 Some Other Street",
city: "Boston",
state: "MA",
zip: "12345"
}
]
}
One-to-Many Relationship with Document References(문서 참조 일대다 관계)
위의 예시와 다르게, 일대다 관계에서 다(Many)의 수가 무한히 증가할 수 있거나(대량이거나), 데이터가 커질 수 있는 경우에는 document안에 저장하는 것 보다는 document를 참조하는 것이 좋을 수 있다.
아래의 예시는 출판사와 책은 일대다 관계를 가지고 있다.
{
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English",
publisher: {
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
}
{
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English",
publisher: {
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
}
일반적으로 책을 조회하고 필요할 경우 출판사에 대한 데이터를 조회하기에 위와 같은 모델이 좋을 수 있다. 하지만, 똑같은 데이터(출판사)가 여러번 반복되기에 비효율적으로 데이터가 저장 되기에 다음과 같이 저장할 수 있다.
{
name: "O'Reilly Media",
founded: 1980,
location: "CA",
books: [123456789, 234567890, ...]
}
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English"
}
{
_id: 234567890,
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English"
}
책을 단독으로 조회할 수 있으며, 출판사를 중복하여 저장할 필요가 없다. 하지만 데이터가 추가 될 때마다 위의 배열이 늘어날 수 있으며, 책 이름을 통하여 출판사를 조회하기는 복잡하다. 따라서 아래와 같이 최종적으로 구상하였다.
{
_id: "oreilly",
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English",
publisher_id: "oreilly"
}
{
_id: 234567890,
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English",
publisher_id: "oreilly"
}
Model Tree Structures(모델 트리 구조)
MongoDB에서 대규모 혹은 계층적 구조를 위한 데이터 관계를 모델링 할 수 있다.
일반적인 모델 트리 구조는 다음과 같다.
또한 트리 구조는 다양한 방식의 구조을 가진다.
Model Tree Structures with Parent References - 부모(상위) 참조가 있는 트리 구조
Model Tree Structures with Child References - 자식(하위) 참조가 있는 트리 구조
Model Tree Structures with an Array of Ancestors - 조상 배열형태의 트리 구조
Model Tree Structures with Materialized Paths - 구체적인 경로를 가진 트리 구조
Model Tree Structures with Nested Sets - 중첩셋을 가진 트리구조
Model Tree Structures with Parent References
먼저 부모 참조가 있는 트리 구조는 위의 그림에서 데이터를 부모(parent)를 명시하여 insert하는 구조이다.
db.categories.insert( { _id: "MongoDB", parent: "Databases" } )
db.categories.insert( { _id: "dbm", parent: "Databases" } )
db.categories.insert( { _id: "Databases", parent: "Programming" } )
db.categories.insert( { _id: "Languages", parent: "Programming" } )
db.categories.insert( { _id: "Programming", parent: "Books" } )
db.categories.insert( { _id: "Books", parent: null } )
따라서 각 노드별로 부모를 구하거나 부모를 통해 노드를 구할 수 있다.
db.categories.findOne( { _id: "MongoDB" } ).parent
db.categories.find( { parent: "Databases" } )
Model Tree Structures with Child References
다음은 자식 참조를 하는 트리구조이다. 위의 부모 참조와 비슷하게 데이터를 자식을 참조하여 insert한다. 자식은 여러개를 가질 수 있다.
db.categories.insert( { _id: "MongoDB", children: [] } )
db.categories.insert( { _id: "dbm", children: [] } )
db.categories.insert( { _id: "Databases", children: [ "MongoDB", "dbm" ] } )
db.categories.insert( { _id: "Languages", children: [] } )
db.categories.insert( { _id: "Programming", children: [ "Databases", "Languages" ] } )
db.categories.insert( { _id: "Books", children: [ "Programming" ] } )
또한 각 노드별 자식을 구하거나, 자식을 통해 노드(부모)를 구할 수 있다.
db.categories.findOne( { _id: "Databases" } ).children
db.categories.find( { children: "MongoDB" } )
위의 부모 참조와 자식 참조들은 부모와 자식필드에 인덱스를 지정하여 빠른 검색을 할 수도 있다.
db.categories.createIndex( { parent: 1 } )
db.categories.createIndex( { children: 1 } )
Model Tree Structures with an Array of Ancestors
조상 배열을 가지는 트리 모델은 각 노드에 ancestors 필드를 함께 명시한다. ancestors 필드는 list로 0번 인덱스 부터 상위 조상이 들어가며 각 단계별 조상을 지정한다. 또한 parent 필드에서는 부모를 참조한다.
db.categories.insert( { _id: "MongoDB", ancestors: [ "Books", "Programming", "Databases" ], parent: "Databases" } )
db.categories.insert( { _id: "dbm", ancestors: [ "Books", "Programming", "Databases" ], parent: "Databases" } )
db.categories.insert( { _id: "Databases", ancestors: [ "Books", "Programming" ], parent: "Programming" } )
db.categories.insert( { _id: "Languages", ancestors: [ "Books", "Programming" ], parent: "Programming" } )
db.categories.insert( { _id: "Programming", ancestors: [ "Books" ], parent: "Books" } )
db.categories.insert( { _id: "Books", ancestors: [ ], parent: null } )
위를 보면 제일 하위노드인 'MongoDB'는 ancestors에 상위 조상들을 포함하지만 최상위인 'Books'는 ancestors를 가지지 않는다.
이러한 구조에서는 각 노드의 조상들을 조회할 수 있으며, 조상을 통해 노드를 찾을 수도 있다.
db.categories.findOne( { _id: "MongoDB" } ).ancestors
db.categories.find( { ancestors: "Programming" } )
Model Tree Structures with Materialized Paths
구체적인 경로를 가진 트리구조는 말 그대로 경로를 작성하여 참조하는 구조이다. path 필드에 각 노드별 경로를 작성하며, 구분자로는 comma(,)를 사용한다.
db.categories.insert( { _id: "Books", path: null } )
db.categories.insert( { _id: "Programming", path: ",Books," } )
db.categories.insert( { _id: "Databases", path: ",Books,Programming," } )
db.categories.insert( { _id: "Languages", path: ",Books,Programming," } )
db.categories.insert( { _id: "MongoDB", path: ",Books,Programming,Databases," } )
db.categories.insert( { _id: "dbm", path: ",Books,Programming,Databases," } )
이 구조에서는 여러가지 조회형태를 가질 수 있다.
먼저 전체 트리를 검색하여 정렬하여 조회할 수 있다.
db.categories.find().sort( { path: 1 } )
또한, 경로 값의 모든 자손을 구할 수 있다.
db.categories.find( { path: /,Programming,/ } )
또한, 최상위 수준의 모든 자손을 구할 수 있다.
db.categories.find( { path: /^,Books,/ } )
Model Tree Structures with Nested Sets
중첩셋은 전체 노드를 탐색하여 통과할 때와 돌아올 때 총 두번의 방문을 하고 그 순서를 명시한다. 따라서 parent 필드와 첫 방문할 때의 순서인 left 필드, 돌아올 때 방문하는 순서인 right 필드 세가지를 참조한다.
db.categories.insert( { _id: "Books", parent: 0, left: 1, right: 12 } )
db.categories.insert( { _id: "Programming", parent: "Books", left: 2, right: 11 } )
db.categories.insert( { _id: "Languages", parent: "Programming", left: 3, right: 4 } )
db.categories.insert( { _id: "Databases", parent: "Programming", left: 5, right: 10 } )
db.categories.insert( { _id: "MongoDB", parent: "Databases", left: 6, right: 7 } )
db.categories.insert( { _id: "dbm", parent: "Databases", left: 8, right: 9 } )
하위 항목을 검색하기 위해 다음과 같이 작성할 수 있다.
var databaseCategory = db.categories.findOne( { _id: "Databases" } );
db.categories.find( { left: { $gt: databaseCategory.left }, right: { $lt: databaseCategory.right } } );
위의 left, right는 규칙이 존재한다.
먼저, 자식인 노드들은 부모보다 right 값이 작으며 left 값은 크다.
따라서, 부모가 아닌 노드는 right 값이 자식보다 작다.
이러한 규칙을 적용해서 부모자식 탐색을 다른 노드보다 빨리할 수 있지만, 수정과정이 매우 어렵다는 단점이 있다.
'Dev-Database > NoSQL' 카테고리의 다른 글
MongoDB Database 참조(References) (0) | 2020.02.05 |
---|---|
MongoDB Model(모델) 활용 (0) | 2020.02.05 |
MongoDB Bulk Write(대랑 쓰기) & Retryable Write(쓰기 재시도) (0) | 2020.02.03 |
MongoDB CRUD 사용(입력, 조회, 수정, 삭제) (1) | 2020.02.03 |
Redis 설치 (Ubuntu 환경) (0) | 2020.01.29 |