เอกสารย่อยพังพอนเทียบกับสคีมาที่ซ้อนกัน


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

นี่คือคำตอบที่ดีเกี่ยวกับข้อควรพิจารณาของ MongoDB ที่ควรถามตัวเองเมื่อสร้างสคีมาฐานข้อมูลของคุณ: stackoverflow.com/questions/5373198/…
anthonylawson

คุณหมายความว่าจำเป็นต้องอธิบาย_idฟิลด์ด้วย? ฉันหมายความว่ามันไม่อัตโนมัติถ้าเปิดใช้งาน?
Vadorequest

มีใครรู้บ้างว่า_idฟิลด์ของเอกสารย่อยไม่ซ้ำกัน? (สร้างโดยใช้วิธีที่ 2 ในคำถามของ OP)
ไซตามะ

คำตอบ:


72

ตามเอกสารมันเหมือนกันทุกประการ อย่างไรก็ตามการใช้สคีมาจะเพิ่ม_idช่องด้วย (ตราบเท่าที่คุณไม่ได้ปิดใช้งาน) และน่าจะใช้ทรัพยากรเพิ่มเติมในการติดตามเอกสารย่อย

ไวยากรณ์การประกาศทางเลือก

ใหม่ใน v3หากคุณไม่ต้องการเข้าถึงอินสแตนซ์สคีมาเอกสารย่อยคุณยังสามารถประกาศเอกสารย่อยได้โดยส่งผ่านอ็อบเจกต์ลิเทอรัล [... ]


1
แต่ฉันพยายามแล้ว เหตุใดข้อมูลเอกสารย่อยจึงไม่ถูกจัดเก็บในคอลเล็กชันแยกต่างหาก เก็บไว้ในคอลเลกชัน mainDoc เสมอ
Fizer Khan

17
นั่นคือวิธีการทำงานของเอกสารย่อย พวกเขากำลังฝังอยู่ภายในเอกสาร ก่อนที่จะเล่นกับพังพอนตรวจสอบให้แน่ใจว่าคุณเข้าใจ MongoDB พื้นฐานแล้ว
AndyL

1
เกี่ยวกับ Schema ที่เพิ่ม _id นั่นเป็นเรื่องที่สมเหตุสมผล แต่ฉันสร้างสคีมาที่มีอาร์เรย์ของเอกสารย่อยและอาร์เรย์ของตัวอักษรอ็อบเจ็กต์และมีการเพิ่ม _id ให้กับทั้งสอง พฤติกรรมเปลี่ยนไปหรือไม่?
Drew Goodwin

@DrewGoodwin ดูเหมือนจะเป็นแบบนี้มาระยะหนึ่งแล้ว: stackoverflow.com/questions/17254008/…
cheesemacfly

37

หากคุณมีสคีมาที่ใช้ซ้ำในส่วนต่างๆของแบบจำลองของคุณการกำหนดสคีมาแต่ละรายการสำหรับเอกสารย่อยอาจมีประโยชน์เพื่อให้คุณไม่ต้องทำซ้ำด้วยตัวเอง


4
นี่คือคำตอบที่ยอดเยี่ยม บางครั้งฉันใช้เอกสารย่อยในโมเดลมากกว่านั้นหรือฉันมีสองฟิลด์ในโมเดลที่ต้องแยกแยะ แต่ยังมีโครงสร้างเอกสารย่อยเหมือนเดิม
Martin Hallén

2
คุณควรคำนึงถึงประโยชน์ / ข้อเสียของการบันทึกข้อมูลที่ซ้ำซ้อน
Sam Vloeberghs

25

คุณควรใช้เอกสารที่ฝังไว้หากเป็นเอกสารคงที่หรือไม่เกินสองสามร้อยเนื่องจากผลกระทบด้านประสิทธิภาพ ฉันได้ผ่านปัญหานั้นมาระยะหนึ่งแล้ว ใหม่ Asya Kamsky ซึ่งทำงานเป็นสถาปนิกโซลูชันของ MongoDB ได้เขียนบทความเกี่ยวกับ "การใช้เอกสารย่อย"

ฉันหวังว่าจะช่วยให้ผู้ที่กำลังมองหาแนวทางแก้ไขหรือแนวทางปฏิบัติที่ดีที่สุด

โพสต์ต้นฉบับบนhttp://askasya.com/post/largeembeddedarrays คุณสามารถเข้าถึงโปรไฟล์ stackoverflow ของเธอได้ที่https://stackoverflow.com/users/431012/asya-kamsky

ก่อนอื่นเราต้องพิจารณาว่าเหตุใดเราจึงต้องการทำสิ่งนั้น โดยปกติฉันจะแนะนำให้ผู้ใช้ฝังสิ่งที่พวกเขาต้องการกลับมาเสมอเมื่อพวกเขาเรียกเอกสารนี้ อีกด้านหนึ่งคือคุณไม่ต้องการฝังสิ่งต่างๆในเอกสารที่คุณไม่ต้องการกลับมาด้วย

หากคุณฝังกิจกรรมที่ฉันทำลงในเอกสารตอนแรกจะใช้งานได้ดีเพราะกิจกรรมทั้งหมดของฉันอยู่ที่นั่นและด้วยการอ่านเพียงครั้งเดียวคุณจะได้รับคืนทุกสิ่งที่คุณอาจต้องการแสดงให้ฉันเห็น: "คุณเพิ่งคลิกที่นี่และที่นี่ สองความคิดเห็นสุดท้ายของคุณ "แต่จะเกิดอะไรขึ้นหลังจากหกเดือนผ่านไปและฉันไม่สนใจสิ่งที่ฉันทำเมื่อนานมาแล้วและคุณไม่ต้องการแสดงให้ฉันเห็นเว้นแต่ฉันจะไปหากิจกรรมเก่า ๆ โดยเฉพาะ?

ขั้นแรกคุณจะต้องส่งคืนเอกสารที่ใหญ่ขึ้นและใหญ่ขึ้นและใส่ใจในส่วนที่เล็กลงและเล็กลง แต่คุณสามารถใช้การฉายภาพเพื่อส่งคืนอาร์เรย์บางส่วนเท่านั้นความเจ็บปวดที่แท้จริงคือเอกสารบนดิสก์จะมีขนาดใหญ่ขึ้นและจะยังคงอ่านได้ทั้งหมดแม้ว่าคุณจะส่งคืนบางส่วนให้กับผู้ใช้ปลายทาง แต่ เนื่องจากกิจกรรมของฉันจะไม่หยุดลงตราบเท่าที่ฉันยังมีการใช้งานเอกสารจะเติบโตและเติบโตอย่างต่อเนื่อง

ปัญหาที่ชัดเจนที่สุดคือในที่สุดคุณจะถึงขีด จำกัด เอกสาร 16MB แต่นั่นไม่ใช่สิ่งที่คุณควรกังวล เอกสารที่เติบโตขึ้นอย่างต่อเนื่องจะต้องเสียค่าใช้จ่ายที่สูงขึ้นและสูงขึ้นทุกครั้งที่ต้องย้ายตำแหน่งบนดิสก์และแม้ว่าคุณจะดำเนินการเพื่อลดผลกระทบจากการแยกส่วนการเขียนของคุณโดยรวมจะยาวโดยไม่จำเป็นซึ่งส่งผลต่อประสิทธิภาพโดยรวมของแอปพลิเคชันทั้งหมดของคุณ

มีอีกสิ่งหนึ่งที่คุณสามารถทำได้ซึ่งจะฆ่าประสิทธิภาพของแอปพลิเคชันของคุณโดยสิ้นเชิงและนั่นคือดัชนีอาร์เรย์ที่เพิ่มขึ้นเรื่อย ๆ นี้ นั่นหมายความว่าทุกครั้งที่ย้ายเอกสารที่มีอาร์เรย์นี้จำนวนรายการดัชนีที่ต้องอัปเดตจะแปรผันตรงกับจำนวนค่าดัชนีในเอกสารนั้นและยิ่งอาร์เรย์มีขนาดใหญ่เท่าใด เป็น

ฉันไม่ต้องการให้สิ่งนี้ทำให้คุณกลัวจากการใช้อาร์เรย์เมื่อมันเหมาะสมกับโมเดลข้อมูล - เป็นคุณสมบัติที่มีประสิทธิภาพของแบบจำลองข้อมูลฐานข้อมูลเอกสาร แต่เช่นเดียวกับเครื่องมือที่มีประสิทธิภาพทั้งหมดจำเป็นต้องใช้ในสถานการณ์ที่เหมาะสม และควรใช้ด้วยความระมัดระวัง


3
นี่น่าจะเป็นคำตอบอันดับต้น ๆ มันปังกับเงิน เอกสารไวท์เปเปอร์ของ MongoDB เองก็พูดได้เหมือนกัน
Jay Edwards

บทความเกี่ยวกับ Bucket Pattern นี้แสดงให้เห็นถึงสิ่งที่ Asya พูดถึงอย่างดี mongodb.com/blog/post/building-with-patterns-the-bucket-patternฉันคิดว่าสคีมา subDoc ในคำถามของ OP จะทำงานได้ดีกับ 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
คำถามไม่ได้ถามว่าจะทำสคีมาที่ซ้อนกันอย่างไร เป็นการอภิปรายว่าพังพอนมีประสิทธิภาพมากขึ้นด้วยสคีมาที่ซ้อนกันหรือเอกสารย่อยที่ฝังไว้ โดยพื้นฐานแล้วเรากำลังพูดถึงเกณฑ์มาตรฐานหรือประเภทหรือกรณีขอบที่พังพอนชอบตัวต่อตัว และตามที่คำตอบที่เลือกกล่าวถึงดูเหมือนว่าจะไม่สร้างความแตกต่างอย่างน้อยก็ตั้งแต่ V3 เป็นต้นไป
cyberwombat

17
อาจจะใช้ไม่ได้กับ OP แต่ฉันพบว่าสิ่งนี้มีประโยชน์มาก ขอบคุณ
Gene Higgins

นี่เป็นสิ่งที่ดีเมื่อมีการประกาศสคีมาทั้ง 3 ในไฟล์. js หนึ่งไฟล์เราจะจัดการกับมันอย่างไรเมื่อประกาศเป็นไฟล์. js 3 ไฟล์ที่แตกต่างกัน
Satyam

9

ฉันคิดว่าสิ่งนี้ได้รับการจัดการที่อื่นโดยหลายโพสต์ใน SO

แค่เล็กน้อย:

กุญแจสำคัญคือไม่มีคำตอบเดียวที่นี่มีเพียงชุดของการแลกเปลี่ยนที่ค่อนข้างซับซ้อน


3
บางทีฉันอาจจะเขียนคำถามไม่ถูกต้อง - นี่ไม่ใช่คำถามว่าฉันควรจัดโครงสร้างฐานข้อมูลของฉันอย่างไร แต่เป็นการใช้ภายในของการใช้สคีมาเทียบกับการเขียนอาร์เรย์ในเลเยอร์ที่ลึกกว่า สาเหตุหลักของฉันในการใช้สคีมาคือฉันสามารถใช้ประโยชน์จากประเภทสคีมาที่กำหนดเองและตรวจสอบความถูกต้องซึ่งเป็นสิ่งที่ใช้ไม่ได้กับอาร์เรย์ที่ซ้อนกัน (จากคำถามก่อนหน้านี้ที่ฉันมีใน SO) ใกล้เคียงที่สุดที่ฉันสามารถบอกได้ว่า subdoc นั้นค่อนข้างเหมือนกับอาร์เรย์ที่ซ้อนกัน - ฉันไม่รู้ว่าภายในของมัน - หากใช้มันจะสร้างปัญหาด้านประสิทธิภาพหรืออย่างนั้น
cyberwombat

0

มีความแตกต่างบางประการระหว่างทั้งสอง:

  • การใช้สคีมาที่ซ้อนกันมีประโยชน์สำหรับการตรวจสอบความถูกต้อง

  • สคีมาที่ซ้อนกันสามารถใช้ซ้ำในสคีมาอื่นได้

  • สคีมาที่ซ้อนกันจะเพิ่มช่อง "_id" ลงในเอกสารย่อยเว้นแต่คุณจะใช้ "_id: false"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.