몽구스 하위 문서와 중첩 스키마


122

내 주 스키마에서 하위 문서와 더 깊은 계층을 사용할 때의 장단점에 대해 궁금합니다.

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});

또는

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

현재 모든 곳에서 하위 문서를 사용하고 있지만 주로 발생할 수있는 성능 또는 쿼리 문제에 대해 궁금합니다.


이 질문에 대한 답을 입력하려고했지만 방법을 찾을 수 없습니다. 하지만 여기를보세요 : mongoosejs.com/docs/subdocs.html
gustavohenke 2013 년

다음은 데이터베이스 스키마를 생성 할 때 자신에게 물어 MongoDB의 고려 사항에 대한 좋은 반응은 다음과 같습니다 stackoverflow.com/questions/5373198/...
anthonylawson은

_id필드를 설명해야한다는 뜻 입니까? 활성화되면 자동으로되지 않나요?
Vadorequest 2014

_id하위 문서 필드가 고유한지 아는 사람이 있습니까? (OP의 질문에 두번째 방법을 사용하여 생성)
사이타마

답변:


72

문서 에 따르면 정확히 동일합니다. 그러나 스키마를 사용하면 _id필드도 추가 되고 (비활성화하지 않는 한) 아마도 하위 문서를 추적하는 데 더 많은 리소스를 사용합니다.

대체 선언 구문

v3의 새로운 기능 하위 문서 스키마 인스턴스에 액세스 할 필요가없는 경우 객체 리터럴 [...]을 전달하여 하위 문서를 선언 할 수도 있습니다.


1
그러나 나는 이것을 시도했다. 하위 문서 데이터가 별도의 컬렉션에 저장되지 않는 이유. 항상 mainDoc 컬렉션에 저장됩니다.
Fizer Khan 2013

17
그것이 하위 문서가 작동하는 방식입니다. 문서 내부에 포함됩니다. 몽구스를 가지고 놀기 전에 기본 MongoDB를 이해해야합니다.
AndyL

1
_id를 추가하는 스키마와 관련하여 의미가 있지만 하위 문서 배열과 개체 리터럴 배열 및 _id가 둘 다에 추가 된 스키마를 만들었습니다. 행동이 바뀌 었습니까?
Drew Goodwin

@DrewGoodwin이 한동안 이렇게 된 것 같습니다 : stackoverflow.com/questions/17254008/…
cheesemacfly

37

모델의 다양한 부분에서 재사용되는 스키마가있는 경우 하위 문서에 대해 개별 스키마를 정의하여 자신을 복제 할 필요가 없도록하는 것이 유용 할 수 있습니다.


4
이것은 훌륭한 대답입니다. 때로는 하나 이상의 모델에서 하위 문서를 사용하거나 구별해야하지만 여전히 동일한 하위 문서 구조를 가진 모델에 두 개의 필드가 있습니다.
Martin Hallén 2014

2
중복 정보 저장의 장점 / 단점도 고려해야합니다.
Sam Vloeberghs 2014

25

정적 문서이거나 성능 영향으로 인해 수백 개 이하인 포함 된 문서를 사용해야합니다. 나는 그 문제에 대해 얼마 전에 겪었습니다. 새로 MongoDB의 솔루션 아키텍트로 일하는 Asya Kamsky는 "하위 문서 사용"에 대한 기사를 작성했습니다.

솔루션이나 모범 사례를 찾는 사람에게 도움이되기를 바랍니다.

http://askasya.com/post/largeembeddedarrays의 원본 게시물 . https://stackoverflow.com/users/431012/asya-kamsky 에서 그녀의 stackoverflow 프로필에 접근 할 수 있습니다.

우선 우리는 왜 그런 일을하고 싶은지 고려해야합니다. 일반적으로 나는 사람들이이 문서를 가져올 때 항상 되찾고 싶은 것을 포함하도록 조언합니다. 이것의 반대면은 문서에 되돌리고 싶지 않은 것을 포함하고 싶지 않다는 것입니다.

내가 수행하는 활동을 문서에 삽입하면 내 모든 활동이 바로 거기에 있고 한 번의 읽기로 내게 보여주고 싶은 모든 것을 다시 가져올 수 있기 때문에 처음에는 훌륭하게 작동 할 것입니다. "최근에 여기를 클릭하고 여기를 클릭했습니다. 마지막 두 개의 댓글이 있습니까? "하지만 6 개월 후에는 어떤 일이 일어나고 나는 오래 전에했던 일에 신경 쓰지 않고 특별히 오래된 활동을 찾아 보지 않는 한 보여주고 싶지 않습니까?

첫째, 더 크고 더 큰 문서를 반환하고 문서의 더 작은 부분을 관리하게됩니다. 그러나 프로젝션을 사용하여 배열의 일부만 반환 할 수 있습니다. 진짜 고통은 디스크의 문서가 커지고 일부만 최종 사용자에게 반환하더라도 여전히 모두 읽을 수 있다는 것입니다. 내가 활동하는 한 내 활동이 멈추지 않을 것이기 때문에 문서는 계속 성장하고 성장할 것입니다.

이것에 대한 가장 명백한 문제는 결국 16MB 문서 제한에 도달하게 될 것이지만 걱정해야 할 것은 전혀 아닙니다. 지속적으로 증가하는 문서는 디스크에 재배치해야 할 때마다 더 많은 비용이 발생하고 조각화의 영향을 완화하기위한 조치를 취하더라도 전체적으로 쓰기가 불필요하게 길어 전체 애플리케이션의 전반적인 성능에 영향을 미칩니다.

응용 프로그램의 성능을 완전히 저하시킬 수있는 또 하나의 방법이 있습니다. 이는 계속해서 증가하는 배열을 인덱싱하는 것입니다. 즉,이 배열이있는 문서가 재배치 될 때마다 업데이트해야하는 색인 ​​항목의 수는 해당 문서의 색인화 된 값 수에 정비례하며 배열이 클수록 해당 숫자가 커집니다. 있다.

데이터 모델에 적합 할 때 배열을 사용하는 것을 두려워하지 않기를 바랍니다. 이는 문서 데이터베이스 데이터 모델의 강력한 기능이지만 모든 강력한 도구와 마찬가지로 올바른 환경에서 사용해야합니다. 주의해서 사용해야합니다.


3
이것이 최고의 대답이어야합니다. 그것은 돈에 강타입니다. MongoDB의 자체 백서에는 거의 동일한 내용이 나와 있습니다.
Jay Edwards

Bucket Pattern에 관한이 기사는 Asya가 멋지게 이야기 한 내용을 칭찬합니다. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern OP 질문의 subDoc 스키마가 Bucket Pattern과 잘 작동 할 것이라고 생각합니다.
plong0

13

기본적으로 변수를 만들고 nestedDov여기에 넣으십시오.name: [nestedDov]

간단한 버전 :

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});

JSON 예

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}

예:

여기에 이미지 설명 입력


1
그것은 성능에 대한 질문을 전혀 다루지 않습니다.
cyberwombat

좀 더 이해하기 위해 약간 편집했습니다. 어떻게 생각해?
Wayne Chiu

3
문제는 중첩 된 스키마를 수행하는 방법을 묻는 것이 아닙니다. Mongoose가 중첩 된 스키마 또는 포함 된 하위 문서에서 성능이 더 우수한 지에 대한 논의입니다. 기본적으로 우리는 Mongoose가 하나를 선호하는 벤치 마크 또는 종류 또는 가장자리 사례에 대해 이야기하고 있습니다. 그리고 선택된 답변에서 언급했듯이 적어도 V3부터는 아무런 차이가없는 것 같습니다.
cyberwombat

17
OP에서는 작동하지 않을 수도 있지만 매우 유용하다는 것을 알았습니다. 감사.
Gene Higgins 2011

3 개의 스키마가 모두 하나의 .js 파일에 선언되어있을 때 유용합니다. 3 개의 다른 .js 파일에서 선언 할 때 어떻게 처리 할 수 ​​있습니까?
Satyam

9

나는 이것이 여러 게시물에 의해 다른 곳에서 처리되었다고 생각합니다.

몇 가지 :

가장 큰 열쇠는 여기에 단 하나의 답이 없다는 것입니다. 단지 다소 복잡한 장단점 만 있습니다.


3
아마도 내 질문을 올바르게 표현하지 않았을 것입니다. 이것은 내 데이터베이스를 어떻게 구성해야하는지에 대한 질문이 아니라 하위 스키마를 사용하는 것보다 더 깊은 계층에 배열을 작성하는 것의 내부 문제입니다. 하위 스키마를 사용하는 주된 원인은 사용자 지정 스키마 유형을 사용하고 유효성을 검사하도록 할 수 있다는 것입니다. (이전 질문에서 SO에 대한 이전 질문에서) 중첩 배열에서 작동하지 않는 것입니다. 내가 말할 수있는 한 subdoc은 중첩 된 배열과 거의 동일하다.-나는 그것의 내부를 알지 못한다.-그것들을 사용하면 성능 문제 등이 발생한다면.
cyberwombat 2013 년

0

둘 사이에는 약간의 차이가 있습니다.

  • 중첩 된 스키마를 사용하면 유효성 검사에 도움이됩니다.

  • 중첩 된 스키마는 다른 스키마에서 재사용 할 수 있습니다.

  • 중첩 된 스키마는 "_id : false"를 사용하지 않는 한 하위 문서에 '_id'필드를 추가합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.