Mongoose alt belgeleri ve iç içe şema karşılaştırması


122

Ana şemamda alt dokümanlar yerine daha derin bir katman kullanmanın artılarını ve eksilerini merak ediyorum:

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

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

veya

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

Şu anda her yerde alt dokümanlar kullanıyorum ancak öncelikle karşılaşabileceğim performans veya sorgulama sorunlarını merak ediyorum.


Sana bir cevap yazmaya çalışıyordum ama nasıl olduğunu bulamadım. Ama buraya bir göz atın: mongoosejs.com/docs/subdocs.html
gustavohenke

Veritabanı
şemanızı

_idAlanı da tanımlaması gerektiğini mi söylediniz? Demek istediğim, etkinleştirilirse otomatik değil mi?
Vadorequest

_idalt belge alanının benzersiz olup olmadığını bilen var mı ? (OP'nin sorusunda 2. yol kullanılarak oluşturulmuştur)
Saitama

Yanıtlar:


72

Dokümanlara göre , tamamen aynı. Ancak, Şema kullanmak bir _idalan da ekler (bunu devre dışı bırakmadığınız sürece) ve muhtemelen alt dokümanları izlemek için daha fazla kaynak kullanır.

Alternatif bildirim sözdizimi

V3'teki yenilikler Alt belge şema örneğine erişmeniz gerekmiyorsa, yalnızca bir nesne değişmezi [...] ileterek alt belgeler de bildirebilirsiniz.


1
Ama bunu denedim. Alt belge verilerinin neden ayrı bir koleksiyonda saklanmadığı. Her zaman mainDoc koleksiyonunda saklanır.
Fizer Khan

17
alt belgeler böyle çalışır. bir belgenin içine gömülüyorlar. firavun faresi ile oynamadan önce, altta yatan MongoDB'yi anladığınızdan emin olun.
AndyL

1
Şema ekleme _id ile ilgili olarak, bu mantıklı, ancak bir dizi alt doküman içeren bir şema oluşturdum ve bir dizi nesne değişmezi ve her ikisine de bir _id eklendi. Davranış değişti mi?
Drew Goodwin

@DrewGoodwin bir süredir böyle görünüyor: stackoverflow.com/questions/17254008/…
cheesemacfly

37

Modelinizin çeşitli bölümlerinde yeniden kullanılan şemalarınız varsa, kendinizi kopyalamak zorunda kalmamak için alt belgeler için ayrı şemalar tanımlamak faydalı olabilir.


4
Bu harika bir cevap. Bazen alt belgeleri birden fazla modelde kullanıyorum veya bir modelde ayırt edilmesi gereken ancak yine de aynı alt belge yapısına sahip iki alanım var.
Martin Hallén

2
Ayrıca gereksiz bilgileri kaydetmenin faydalarını / dezavantajlarını da göz önünde bulundurmalısınız.
Sam Vloeberghs

25

Statik belgeler ise veya performans etkisi nedeniyle birkaç yüzü aşmayan katıştırılmış belgeler kullanmalısınız. Bu konuyu bir süre önce yaşadım. Yeni olarak MongoDB için çözüm mimarı olarak çalışan Asya Kamsky, "alt belgeleri kullanma" hakkında bir makale yazmıştı.

Umarım bu, çözümleri veya en iyi uygulamayı arayanlara yardımcı olur.

Orijinal sonrası http://askasya.com/post/largeembeddedarrays . Stackoverflow profiline https://stackoverflow.com/users/431012/asya-kamsky adresinden ulaşabilirsiniz.

Her şeyden önce, neden böyle bir şey yapmak isteyeceğimizi düşünmeliyiz. Normalde, insanlara bu belgeyi getirirken her zaman geri almak istedikleri şeyleri yerleştirmelerini tavsiye ederim. Bunun diğer tarafı, belgeye geri dönmek istemediğiniz şeyleri gömmek istememenizdir.

Yaptığım etkinliği belgeye katıştırırsanız, ilk başta harika çalışır, çünkü tüm etkinliklerim orada ve tek bir okuma ile bana göstermek isteyebileceğiniz her şeyi geri alabilirsiniz: "Yakın zamanda bunu ve burayı tıkladınız son iki yorumunuz mu? "ama altı ay sonra ne olacak ve uzun zaman önce yaptığım şeyler umrumda değil ve özellikle eski bir aktiviteyi aramaya gitmedikçe bunları bana göstermek istemiyorsunuz?

İlk olarak, daha büyük ve daha büyük bir belgeyi geri getirecek ve daha küçük ve daha küçük bir kısmını önemseyeceksiniz. Ancak dizinin yalnızca bir kısmını döndürmek için projeksiyonu kullanabilirsiniz, asıl acı, diskteki belgenin büyüyeceği ve yalnızca bir kısmını son kullanıcıya iade edecek olsanız bile yine de tümünün okunacağıdır, ancak Faaliyetim aktif olduğum sürece durmayacağı için belge büyümeye ve büyümeye devam edecek.

Bununla ilgili en belirgin sorun, sonunda 16MB belge sınırına ulaşmanızdır, ancak endişelenmeniz gereken şey bu değil. Sürekli büyüyen bir belge, diske her taşınması gerektiğinde daha yüksek maliyete neden olur ve parçalanmanın etkilerini azaltmak için adımlar atsanız bile, yazmalarınız genel olarak gereksiz şekilde uzun olur ve tüm uygulamanızın genel performansını etkiler.

Yapabileceğiniz, uygulamanızın performansını tamamen öldürecek bir şey daha var ve bu sürekli artan diziyi indekslemek. Bunun anlamı, bu diziye sahip belge her yeniden konumlandırıldığında, güncellenmesi gereken dizin girişlerinin sayısı o belgedeki dizinlenmiş değerlerin sayısı ile doğru orantılıdır ve dizi ne kadar büyükse, bu sayı o kadar büyük olacaktır. olmak.

Bunun, veri modeline uygun olduklarında dizileri kullanmaktan sizi korkutmasını istemiyorum - bunlar belge veritabanı veri modelinin güçlü bir özelliğidir, ancak tüm güçlü araçlar gibi, doğru koşullarda kullanılması gerekir dikkatli kullanılmalıdır.


3
Bu en iyi cevap olmalı; paranın üstüne vuruyor. MongoDB'nin kendi teknik incelemeleri hemen hemen aynı şeyi söylüyor.
Jay Edwards

Kova Deseni hakkındaki bu makale, Asya'nın güzel bir şekilde bahsettiklerini tamamlıyor. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern OP'nin sorusundaki subDoc şemasının Bucket Pattern ile iyi çalışacağını düşünüyorum.
plong0

13

Temel olarak, bir değişken oluşturun nestedDovve buraya koyunname: [nestedDov]

Basit Sürüm:

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

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

JSON Örneği

{
    "_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"
    ]
}

Misal:

görüntü açıklamasını buraya girin


1
Bu, performansla ilgili soruyu hiç ele almıyor.
cyberwombat

Daha anlamlı olması için biraz düzenledim. Ne düşünüyorsun?
Wayne Chiu

3
Soru, iç içe geçmiş şemaların nasıl yapılacağını sormak değil. Mongoose'un iç içe geçmiş şemalar veya gömülü alt belgelerle daha performanslı olup olmadığı üzerine bir tartışma. Temel olarak, Mongoose'un birini diğerine tercih ettiği ölçütlerden veya sıralamalardan veya uç durumlardan bahsediyoruz. Ve seçilen yanıtın bahsettiği gibi, en azından V3'ten itibaren herhangi bir fark yaratmıyor gibi görünüyor.
cyberwombat

17
Belki OP için işe yaramıyor, ama bunu çok yararlı buldum. Teşekkürler.
Gene Higgins

Bu, 3 şema tek bir .js dosyasında bildirildiğinde iyidir, 3 farklı .js dosyasında bildirildiğinde bunu nasıl halledebiliriz?
Satyam

9

Sanırım bu başka bir yerde SO'da birden fazla gönderi ile ele alındı.

Sadece birkaç tane:

Buradaki en büyük anahtar, burada tek bir cevap olmaması, yalnızca oldukça karmaşık bir dizi değiş tokuşun olmasıdır.


3
Belki de sorumu doğru bir şekilde ifade etmiyorum - Bu, veritabanımı nasıl yapılandırmam gerektiği değil, daha çok bir alt şema kullanmanın dahili unsurları ile diziyi daha derin bir katmana yazmanın bir sorusudur. Bir alt şemayı kullanmamın birincil nedeni, özel şema türlerini kullanabilmem ve onları doğrulatabilmemdir - iç içe dizilerle çalışmayan bir şey (SO'da sorduğum önceki bir sorudan). Bir alt dokümanın iç içe geçmiş bir diziyle hemen hemen aynı olduğunu söyleyebildiğim kadarıyla - sadece içsellerini bilmiyorum - eğer onları kullanmak performans sorunları yaratacaksa.
cyberwombat

0

İkisi arasında bazı farklar var:

  • İç içe geçmiş şema kullanmak, doğrulama için faydalıdır.

  • İç içe geçmiş şema, diğer şemalarda yeniden kullanılabilir.

  • İç içe yerleştirilmiş şema, "_id: false" kullanmadıysanız alt belgeye "_id" alanını ekleyin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.