[mongodb] MongoDB 관계 : 포함 또는 참조?

관계형 데이터베이스 배경에서 온 MongoDB를 처음 사용합니다. 나는 약간의 의견에 질문의 구조를 설계 할,하지만 난 의견에 사용할 관계 모르는 : embedreference?

stackoverflow 와 같은 주석이있는 질문은 다음과 같은 구조를 갖습니다.

Question
    title = 'aaa'
    content = bbb'
    comments = ???

처음에는 embed다음과 같이 포함 된 주석 ( MongoDB에서 권장되는 것으로 생각합니다 )을 사용하고 싶습니다.

Question
    title = 'aaa'
    content = 'bbb'
    comments = [ { content = 'xxx', createdAt = 'yyy'},
                 { content = 'xxx', createdAt = 'yyy'},
                 { content = 'xxx', createdAt = 'yyy'} ]

분명하지만이 사건에 대해 걱정 합니다. 지정된 의견을 편집하려면 내용과 질문을 어떻게 얻습니까? 더 없다 _id내가 하나를 찾을 수 없으며, question_ref내가 그 질문을 찾을 수 있습니다. (저는 초보자가 아니기 때문에 _id및 없이이 작업을 수행 할 방법이 있는지 모르겠습니다 question_ref.)

사용 ref하지 않아야 embed합니까? 그런 다음 주석을위한 새 컬렉션을 만들어야합니까?



답변

이것은 과학보다 예술입니다. 스키마에 대한 몽고 문서 는 좋은 참고 자료이지만 고려해야 할 사항이 있습니다.

  • 가능한 많이 넣어

    문서 데이터베이스의 즐거움은 많은 조인을 제거한다는 것입니다. 첫 번째 본능은 가능한 한 단일 문서에 배치해야합니다. MongoDB 문서에는 구조가 있고 해당 구조 내에서 효율적으로 쿼리 할 수 ​​있기 때문에 (필요한 문서의 일부를 취할 수 있으므로 문서 크기는 크게 걱정하지 않아도 됨) 데이터를 즉시 정규화 할 필요가 없습니다. 당신은 SQL에서 할 것입니다. 특히, 상위 문서와 별도로 유용하지 않은 데이터는 동일한 문서의 일부 여야합니다.

  • 여러 장소에서 참조 할 수있는 데이터를 자체 컬렉션으로 분리합니다.

    이것은 “데이터 일관성”문제이므로 “스토리지 공간”문제는 아닙니다. 많은 레코드가 동일한 데이터를 참조 할 경우 단일 레코드를 업데이트하고 다른 위치에 참조를 유지하는 것이 더 효율적이고 오류가 적습니다.

  • 문서 크기 고려 사항

    MongoDB는 단일 문서에 4MB (16MB, 1.8) 크기 제한을 적용합니다. GB의 데이터 세계에서는이 소리가 작게 들리지만 30 만 트윗 또는 250 개의 일반적인 스택 오버플로 응답 또는 20 번 깜박임 사진입니다. 반면에, 이것은 일반적인 웹 페이지에 한 번에 제시하고자하는 것보다 훨씬 많은 정보입니다. 먼저 쿼리를보다 쉽게 ​​만드는 방법을 고려하십시오. 대부분의 경우 문서 크기에 대한 우려는 조기 최적화입니다.

  • 복잡한 데이터 구조 :

    MongoDB는 임의의 깊은 중첩 데이터 구조를 저장할 수 있지만 효율적으로 검색 할 수는 없습니다. 데이터가 트리, 포리스트 또는 그래프를 형성하는 경우 각 노드와 해당 가장자리를 별도의 문서에 효과적으로 저장해야합니다. (이 유형의 데이터를 위해 특별히 설계된 데이터 저장소도 고려해야합니다.)

    또한 문서에서 요소의 하위 집합을 반환하는 것이 불가능하다는 것보다 지적되었습니다 . 각 문서의 몇 비트를 골라서 선택해야하는 경우 분리하기가 더 쉬울 것입니다.

  • 데이터 일관성

    MongoDB는 효율성과 일관성 사이에서 균형을 유지합니다. 규칙은 단일 문서에 대한 변경 사항은 항상 원 자성이지만 여러 문서에 대한 업데이트 는 원 자성으로 간주해서는 안됩니다. 서버에서 레코드를 “잠그는”방법도 없습니다 (예 : “잠금”필드를 사용하여이를 클라이언트의 논리에 구축 할 수 있음). 스키마를 디자인 할 때 데이터 일관성을 유지하는 방법을 고려하십시오. 일반적으로 문서에 많이 보관할수록 좋습니다.

설명하는 내용에 대해 설명을 포함시키고 각 설명에 ObjectID가있는 id 필드를 제공합니다. ObjectID에는 타임 스탬프가 포함되어 있으므로 원하는 경우 만든 대신 사용할 수 있습니다.


답변

일반적으로 엔터티간에 일대일 또는 일대 다 관계가 있으면 포함이 좋고, 다 대다 관계가 있으면 참조가 좋습니다.


답변

지정된 주석을 편집하려면 내용과 질문을 얻는 방법은 무엇입니까?

하위 문서별로 쿼리 할 수 ​​있습니다 : db.question.find({'comments.content' : 'xxx'}).

그러면 전체 질문 문서가 반환됩니다. 지정된 주석을 편집하려면 클라이언트에서 주석을 찾아서 편집 한 후 DB에 다시 저장해야합니다.

일반적으로 문서에 객체 배열이 포함되어 있으면 해당 하위 객체를 클라이언트 쪽에서 수정해야합니다.


답변

글쎄, 나는 조금 늦었지만 여전히 내 스키마 생성 방식을 공유하고 싶습니다.

고전 OOP에서와 마찬가지로 단어로 설명 할 수있는 모든 것에 대한 스키마가 있습니다.

EG

  • 논평
  • 계정
  • 사용자
  • 블로그 포스트

모든 스키마는 문서 또는 하위 문서로 저장 될 수 있으므로 각 스키마마다이를 선언합니다.

문서:

  • 참조로 사용할 수 있습니다. (예 : 사용자가 의견을 작성했습니다.-> 의견은 사용자에 대한 “제작자”참조입니다.)
  • 응용 프로그램의 “루트”입니다. (예 : 블로그 포스트-> 블로그 포스트에 관한 페이지가 있습니다)

하위 문서 :

  • 한 번만 사용할 수 있으며 참조가 아닙니다. (예 : 댓글은 블로그 포스트에 저장됩니다)
  • 응용 프로그램에서 “루트”가 아닙니다. (댓글은 블로그 포스트 페이지에 표시되지만 해당 페이지는 여전히 블로그 포스트에 관한 것입니다)

답변

나는이 질문을 스스로 조사 하면서이 작은 프레젠테이션을 보았습니다. 나는 정보와 정보의 표현이 얼마나 잘 구성되어 있는지 놀랐다.

http://openmymind.net/Multiple-Collections-Versus-Embedded-Documents

요약했습니다 :

일반적으로 [자식 문서]가 많거나 큰 경우에는 별도의 모음이 가장 좋습니다.

더 작거나 적은 문서는 자연스럽게 포함시키는 경향이 있습니다.


답변

나는 이것이 아주 오래되었다는 것을 알고 있지만 지정된 주석 만 반환하는 방법에 대한 OP의 질문에 대한 답을 찾고 있다면 $ (조회) 연산자를 다음과 같이 사용할 수 있습니다 .

db.question.update({'comments.content': 'xxx'}, {'comments.$': true})


답변

예, 우리는 문서의 참조를 사용할 수 있습니다 .SQL i 조인과 같은 다른 문서를 채우려면 mongo db에서는 하나의 많은 관계 문서에 매핑하는 조인이 없습니다. 대신 채우기 를 사용 하여 시나리오를 수행 할 수 있습니다.

var mongoose = require('mongoose')
  , Schema = mongoose.Schema

var personSchema = Schema({
  _id     : Number,
  name    : String,
  age     : Number,
  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});

var storySchema = Schema({
  _creator : { type: Number, ref: 'Person' },
  title    : String,
  fans     : [{ type: Number, ref: 'Person' }]
});

인구는 문서의 지정된 경로를 다른 컬렉션의 문서로 자동으로 바꾸는 프로세스입니다. 단일 문서, 여러 문서, 일반 개체, 여러 일반 개체 또는 쿼리에서 반환 된 모든 개체를 채울 수 있습니다. 몇 가지 예를 살펴 보겠습니다.

더 자세한 정보는 http://mongoosejs.com/docs/populate.html을 참조하십시오.