2009-12-05 52 views
7

İç içe geçmiş kümeleri (yorum ağaçları gibi) MongoDB'de depolamanın en iyi yöntemleri nelerdir?MongoDB iç içe kümeler

Her yorumun bir ebeveyn yorumu ve çocuk yorumları (yanıtları) olabilir.

bu gibi onları saklanması: Biz, örneğin, harita olmadan "Peter tarafından yorumladı tüm post" için talep edemez, çünkü

{ 
    title: "Hello", 
    body: "Please comment me!", 
    comments: [ 
     { 
      author: "Peter", 
      text: "Hi there", 
      answers: [ 
        { 
         author: "Peter", 
         text: "Hi there", 
         answers: [ 
           { author: "Ivan", text: "Hi there" }, 
           { author: "Nicholas", text: "Hi there" } 
         ] 
        }, 
        { author: "Ivan", text: "Hi there" }, 
        { author: "Nicholas", text: "Hi there" }, 
      ] 
     }, 
     { author: "Ivan", text: "Hi there" }, 
     { author: "Nicholas", text: "Hi there" }, 
    ] 
} 

hiç hoş değil/azaltır.

cevap

3

Mükemmel bir çözüm olmadığını düşünüyorum - uygulamanız için hangi işlemlerin daha önemli olduğuna bağlı olarak. Örneğin, Silicon Alley Insider'ın MongoDB ile iç içe geçmiş yorumları sakladığına inanıyorum. Bu, daha fazla konuştuğunuz sorguyu yapar.

Bir seçenek, bir dizideki tüm yorum yapanların bir listesini postayla en üst düzeyde depolar. Bunu denormalize edilmiş veriler olarak düşün. Sonra belirli bir yorumcu içeren tüm mesajları kolayca bulabilirsiniz. Daha sonra dataya inmek için, iç içe geçmiş posta bilgilerini almak için harita/küçült veya db.eval() öğesini kullanın.

Diğer bir not - eğer tek bir belge ile uğraşıyorsanız, db.eval() büyük olasılıkla harita/küçültmekten daha hafiftir. $ bir seçenek de var ama yavaş olabilir, bu yüzden yukarıda bahsedilen 'yorum yapanlar listesi' ni de beğeniyorum - bu diziyi de dizine eklememek de kolay değil (dokümanlardaki 'Multikey'e bakın).

Ayrıca bkz: dm yayınının Dwight Merriman gelen linkte http://groups.google.com/group/mongodb-user/browse_thread/thread/df8250573c91f75a/e880d9c57e343b52?lnk=gst&q=trees#e880d9c57e343b52

2

dizilerle olurdu bunu yapmanın bir yolu tuşunu kullanarak bahseder ve başka şekilde regex

{ 
    path : "a.b.c.d.e.f" 
} 

maçlarının yapıyor

{ 
    path : ["a", "b", "c", "d", "e", "f"] 
} 

db.test.ensureIndex({path: 1}) 

bunu oldukça hızlı yapmalıdır. Her düğüm sadece tek bir yolu olabilir eğer

o zaman "a"

tüm çocukları bulur listede

db.test.find({path: "a"}) 

içinde bulunduğu dert yapmaya gerek olmaz Yol adları yerine, muhtemelen düğümlerin _id'sini kullanırdım. dikkatli olmak

Güncelleme

  • bir şey bir dizin sadece içinde bir dizi var olabilir.
  • sorgularınızdan

    db.test üzerinde açıklamak kullanmaya dikkat edin.bulmak ({yolu: {$ in: [ "a", "b"]})

size

db.test.find({path: {$in: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1 multi", 
     "nscanned" : 2, 
     "nscannedObjects" : 2, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ], 
         [ 
           "b", 
           "b" 
         ] 
       ] 
     } 
} 

ama

db.test.find({path: {$all: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1", 
     "nscanned" : 1, 
     "nscannedObjects" : 1, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ] 
       ] 
     } 
} 

sadece ilk öğesini kullanan ve verir daha sonra tüm eşleşen sonuçları tarar.
Kök öğeniz ya da kayıtlarınızın çoğundaysa, verimli bir dizin sorgusu yerine kayıtların neredeyse tamamı taranıyor demektir.