MongoDB'de veri versiyonlama uygulama yolları


298

MongoDB'de veri versiyonlamasını nasıl uygulayacağınızı düşüncelerinizi paylaşabilir misiniz? ( Cassandra ile ilgili benzer bir soru sordum . Bunun için db'nin daha iyi olduğu düşünceleriniz varsa lütfen paylaşın)

Basit bir adres defterinde kayıtları sürümüne ihtiyacım olduğunu varsayalım. (Adres defteri kayıtları düz json nesneleri olarak saklanır). Tarihin:

  • seyrek olarak kullanılacak
  • bir "zaman makinesi" tarzında sunmak için bir kerede kullanılacak
  • tek bir kaydın birkaç yüzden fazla sürümü olmayacak. tarihin süresi dolmaz.

Aşağıdaki yaklaşımları düşünüyorum:

  • Kayıtların geçmişini veya kayıtlardaki değişiklikleri saklamak için yeni bir nesne koleksiyonu oluşturun. Adres defteri girişine referansla sürüm başına bir nesne depolardı. Bu tür kayıtlar aşağıdaki gibi görünecektir:

    {
     '_id': 'yeni kimlik',
     'kullanıcı': kullanıcı_kimliği,
     'zaman damgası': zaman damgası,
     'address_book_id': 'adres defteri kaydının kimliği' 
     'old_record': {'first_name': 'Jon', 'last_name': 'Doe' ...}
    }
    

    Bu yaklaşım, belge başına bir dizi sürümü saklayacak şekilde değiştirilebilir. Ancak bu herhangi bir avantaj olmaksızın daha yavaş bir yaklaşım gibi görünmektedir.

  • Sürümleri, adres defteri girişlerine eklenmiş serileştirilmiş (JSON) nesne olarak depolayın. MongoDB belgelerine bu tür nesnelerin nasıl ekleneceğinden emin değilim. Belki bir dizi dizisi olarak. ( CouchDB ile Basit Belge Sürümlendirmesinden sonra modellenmiştir )


1
Soru cevaplandığından beri bunun değişip değişmediğini bilmek istiyorum. Oplog hakkında çok şey bilmiyorum ama o zamanlar buralarda mıydı, fark eder mi?
Randy L

Yaklaşımım tüm verileri bir zaman serisi olarak düşünmektir.

Yanıtlar:


152

Buna dalırken ilk büyük soru "değişim setlerini nasıl saklamak istersiniz" dir .

  1. Diffs?
  2. Tüm kopyalar mı?

Kişisel yaklaşımım farkları depolamak olacaktır. Bu farkların gösterimi gerçekten özel bir işlem olduğundan, farkları farklı bir "tarih" koleksiyonuna koyarım.

Bellek alanından tasarruf etmek için farklı koleksiyonu kullanırdım. Genellikle basit bir sorgu için tam geçmiş istemezsiniz. Dolayısıyla, geçmişi nesneden uzak tutarak, bu veriler sorgulandığında, yaygın olarak erişilen bellekten de uzak tutabilirsiniz.

Hayatımı kolaylaştırmak için bir tarih belgesinin zaman damgalı farkların sözlüğünü içermesini sağlarım. Bunun gibi bir şey:

{
    _id : "id of address book record",
    changes : { 
                1234567 : { "city" : "Omaha", "state" : "Nebraska" },
                1234568 : { "city" : "Kansas City", "state" : "Missouri" }
               }
}

Hayatımı gerçekten kolaylaştırmak için, verilerime erişmek için kullandığım DataObjects'imin (EntityWrapper, ne olursa olsun) bu kısmını yapardım. Genellikle bu nesnelerin bir tür geçmişi vardır, böylece save()bu değişikliği aynı anda yapmak için yöntemi kolayca geçersiz kılabilirsiniz .

GÜNCELLEME: 2015-10

Görünüşe göre artık JSON diffs ile ilgili bir özellik var . Bu, farkları / değişiklikleri saklamanın daha sağlam bir yolu gibi görünüyor.


2
Böyle bir Geçmiş belgesinin (değişiklikler nesnesi) zaman içinde büyüyeceği ve güncellemelerin verimsiz hale geleceği konusunda endişelenmez misiniz? Yoksa MongoDB tanıtıcı belge kolayca büyüyor mu?
Piotr Czapla

5
Düzenlemeye bir göz atın. Eklemek changesgerçekten çok kolay: db.hist.update({_id: ID}, {$set { changes.12345 : CHANGES } }, true)Bu, yalnızca gerekli verileri değiştirecek bir yükseltme gerçekleştirecektir. Mongo bu tür bir değişikliği gerçekleştirmek için "arabellek alanı" olan belgeler oluşturur. Ayrıca bir koleksiyondaki belgelerin nasıl değiştiğini izler ve her koleksiyon için arabellek boyutunu değiştirir. Bu nedenle MongoDB tam olarak bu tür bir değişiklik için tasarlanmıştır (diziye yeni özellik / push ekle).
Gates VP

2
Bazı testler yaptım ve gerçekten de yer rezervasyonu oldukça iyi çalışıyor. Kayıtlar veri dosyasının sonuna yeniden tahsis edildiğinde performans kaybını yakalayamadım.
Piotr Czapla

4
Geçmişiniz için (MongoDB uyumlu) farklar oluşturmak için github.com/mirek/node-rus-diff kullanabilirsiniz .
Mirek Rusin

1
JSON Yama RFC difffs ifade etmek için bir yol sağlar. It has birçok dilde uygulamaları .
Jérôme

31

Diğer yanıtlarda ele alınmayan bazı yönleri ele alan "Vermongo" adında bir versiyonlama şeması vardır.

Bu sorunlardan biri eşzamanlı güncellemeler, diğeri dokümanları silmektir.

Vermongo tam belge kopyalarını bir gölge koleksiyonunda saklar. Bazı kullanım durumlarında bu çok fazla ek yüke neden olabilir, ancak bence birçok şeyi de basitleştirir.

https://github.com/thiloplanz/v7files/wiki/Vermongo


5
Aslında nasıl kullanıyorsunuz?
hadees

6
Bu projenin gerçekte nasıl kullanıldığı hakkında hiçbir belge yoktur. Bir şekilde Mongo ile yaşayan bir şey mi? Bu bir Java kütüphanesi mi? Bu sadece sorunu düşünmenin bir yolu mu? Hiçbir fikir ve ipucu verilmez.
ftrotter

1
Bu aslında bir java uygulaması ve ilgili kod burada yaşıyor: github.com/thiloplanz/v7files/blob/master/src/main/java/v7db/…
ftrotter

20

Geçerli sürüm ve tüm eski sürümler için tek bir belge kullanan başka bir çözüm:

{
    _id: ObjectId("..."),
    data: [
        { vid: 1, content: "foo" },
        { vid: 2, content: "bar" }
    ]
}

datatüm sürümleri içerir . dataDizi edilir sipariş yeni versiyonları sadece alacak, $pushdizinin sonuna ed. data.vidartan bir sayı olan sürüm kimliğidir.

En son sürümü edinin:

find(
    { "_id":ObjectId("...") },
    { "data":{ $slice:-1 } }
)

Belirli bir sürümü aşağıdaki yollarla edinin vid:

find(
    { "_id":ObjectId("...") },
    { "data":{ $elemMatch:{ "vid":1 } } }
)

Yalnızca belirtilen alanları döndür:

find(
    { "_id":ObjectId("...") },
    { "data":{ $elemMatch:{ "vid":1 } }, "data.content":1 }
)

Yeni sürüm ekle: (ve eşzamanlı ekleme / güncellemeyi önle)

update(
    {
        "_id":ObjectId("..."),
        $and:[
            { "data.vid":{ $not:{ $gt:2 } } },
            { "data.vid":2 }
        ]
    },
    { $push:{ "data":{ "vid":3, "content":"baz" } } }
)

2, viden güncel sürümdür ve 3eklenen yeni sürümdür. İhtiyacınız Çünkü en son sürümü en vid, bir sonraki versiyon en olsun kolaydır vid: nextVID = oldVID + 1.

$andDurum yani sağlayacaktır 2sonuncusu vid.

Bu şekilde benzersiz bir dizine gerek kalmaz, ancak uygulama mantığı ek vidparçanın artırılmasına dikkat etmelidir .

Belirli bir sürümü kaldırın:

update(
    { "_id":ObjectId("...") },
    { $pull:{ "data":{ "vid":2 } } }
)

Bu kadar!

(doküman sınırı başına 16 MB'yi unutmayın)


Mmapv1 depolama ile, verilere her yeni sürüm eklendiğinde, belgenin taşınması olasılığı vardır.
raok1997

Evet bu doğru. Ancak arada bir yeni sürümler eklerseniz, bu ihmal edilebilir olmalıdır.
Benjamin M


9

Verilerin yayınlanmış, taslak ve geçmiş sürümlerini barındıran bu çözüm üzerinde çalıştım:

{
  published: {},
  draft: {},
  history: {
    "1" : {
      metadata: <value>,
      document: {}
    },
    ...
  }
}

Modeli burada daha ayrıntılı olarak açıklarım: http://software.danielwatrous.com/representing-revision-data-in-mongodb/

Java'da böyle bir şey uygulayabilenler için bir örnek:

http://software.danielwatrous.com/using-java-to-work-with-versioned-data/

İsterseniz çatallayabileceğiniz tüm kodlar dahil

https://github.com/dwatrous/mongodb-revision-objects


Harika şeyler :)
Jonathan


4

Başka bir seçenek, mongoose geçmişi eklentisini kullanmaktır .

let mongoose = require('mongoose');
let mongooseHistory = require('mongoose-history');
let Schema = mongoose.Schema;

let MySchema = Post = new Schema({
    title: String,
    status: Boolean
});

MySchema.plugin(mongooseHistory);
// The plugin will automatically create a new collection with the schema name + "_history".
// In this case, collection with name "my_schema_history" will be created.

1

Bir meteor / MongoDB projesi için aşağıdaki paketi kullandım ve iyi çalışıyor, ana avantajı, geçmişi / revizyonları aynı belgedeki bir dizi içinde saklaması, dolayısıyla değişiklik geçmişine erişmek için ek yayınlara veya ara katman yazılımına gerek olmamasıdır. . Sınırlı sayıda önceki sürümü (örn. Son on sürüm) destekleyebilir, ayrıca değişiklik birleştirme işlemini de destekler (böylece belirli bir süre içinde gerçekleşen tüm değişiklikler bir revizyon kapsamında olacaktır).

nicklozon / meteor koleksiyonu-revizyonları

Başka bir ses seçeneği Meteor Vermongo'yu kullanmaktır ( burada )

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.