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


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.