2010-11-15 17 views
249

Czy możesz podzielić się swoimi przemyśleniami na temat implementacji wersji danych w MongoDB? (Pytałem: similar question regarding Cassandra. Jeśli masz jakieś przemyślenia, które db jest lepsze, podziel się tym tematem)Sposoby implementacji wersji danych w MongoDB

Załóżmy, że potrzebuję wersji rekordów w prostej książce adresowej. (Rekordy książki adresowej są przechowywane jako płaskie obiekty json). Spodziewam się, że historia:

  • będą wykorzystywane rzadko
  • zostaną wykorzystane wszystkie naraz, aby przedstawić go w „Time Machine” moda
  • nie będzie więcej niż wersje kilkuset do pojedynczy rekord. historia nie wygaśnie.

Zastanawiam następujące podejścia:

  • Utwórz nową kolekcję obiektów do przechowywania historii zmian do rejestrów lub ewidencji. Będzie przechowywać jeden obiekt na wersję z odniesieniem do wpisu książki adresowej. Takie zapisy wyglądają następująco:

     
    { 
    '_id': 'new id', 
    'user': user_id, 
    'timestamp': timestamp, 
    'address_book_id': 'id of the address book record' 
    'old_record': {'first_name': 'Jon', 'last_name':'Doe' ...} 
    } 
    

    To podejście można zmodyfikować, aby przechowywać tablicę wersji dla każdego dokumentu. Ale wydaje się to wolniejszym podejściem bez żadnych korzyści.

  • Zapisuje wersje jako obiekt serializowany (JSON) dołączony do wpisów w książce adresowej. Nie wiem, jak dołączyć takie obiekty do dokumentów MongoDB. Być może jako tablica ciągów. (Modelled after Simple Document Versioning with CouchDB)

+0

Chcę się dowiedzieć, czy to się zmieniło od czasu udzielenia odpowiedzi na pytanie? Nie wiem zbyt wiele na temat oploga, ale czy było to w tym czasie, czy to miałoby znaczenie? – the0ther

+0

Moje podejście to myślenie o wszystkich danych jako szeregu czasowego. –

Odpowiedz

123

Pierwszy duży problem podczas nurkowania na tym komputerze jest „jak chcesz przechowywać Zestawienia zmian”?

  1. Diffs?
  2. Całe kopie nagrań?

Moim osobistym podejściem byłoby przechowywanie różnic. Ponieważ wyświetlanie tych różnic jest naprawdę specjalną akcją, umieściłbym różnice w innej kolekcji "historii".

Chciałbym użyć różnych kolekcji, aby zaoszczędzić miejsce w pamięci. Zwykle nie chcesz pełnej historii dla prostego zapytania. Tak więc, utrzymując historię poza obiektem, możesz także zachować ją poza powszechnie dostępną pamięcią, gdy dane są sprawdzane.

Aby moje życie było łatwe, chciałbym, aby dokument historii zawierał słownik znaczników czasu. Coś takiego:

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

Aby uczynić moje życie naprawdę proste, chciałbym uczynić tę część moich DataObjects (EntityWrapper, cokolwiek), które używam dostęp do moich danych. Zasadniczo obiekty te mają pewną formę historii, dzięki czemu można łatwo zastąpić metodę save(), aby wprowadzić tę zmianę w tym samym czasie.

UPDATE: 2015-10

Wygląda na to, że jest teraz a spec for handling JSON diffs.Wydaje się to być bardziej niezawodnym sposobem przechowywania różnic/zmian.

+2

Nie martwiłbyś się, że taki dokument historii (obiekt zmian) będzie rósł w czasie, a aktualizacje staną się nieefektywne? Czy też MongoDB radzi sobie z łatwością w tworzeniu dokumentów? –

+5

Spójrz na edycję. Dodanie do 'zmian' jest naprawdę łatwe:' db.hist.update ({_ id: ID}, {$ zestaw {zmiany.12345: ZMIANY}}, prawda) 'Spowoduje to przeprowadzenie upsert, który zmieni tylko wymagane dane. Mongo tworzy dokumenty z "przestrzenią buforową" do obsługi tego typu zmiany. Monitoruje również sposób zmiany dokumentów w kolekcji i modyfikuje rozmiar bufora dla każdej kolekcji. Tak więc MongoDB jest przeznaczony do dokładnie tego rodzaju zmiany (dodaj nową właściwość/push do tablicy). –

+2

Zrobiłem kilka testów i rzeczywiście rezerwacja miejsca działa całkiem nieźle. Nie mogłem złapać utraty wydajności, gdy rekordy zostały ponownie przydzielone na końcu pliku danych. –

26

jest versi program "Vermongo", który dotyczy niektórych aspektów, które nie zostały uwzględnione w innych odpowiedziach.

Jednym z tych problemów są aktualizacje równoczesne, kolejnym jest usuwanie dokumentów.

Vermongo przechowuje kompletne kopie dokumentów w kolekcji cieni. W niektórych przypadkach może to spowodować zbyt duży narzut, ale myślę, że to również upraszcza wiele rzeczy.

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

+0

miłe znalezisko, dziękuję – redben

+4

Jak właściwie go używasz? – hadees

+3

Nie ma dokumentacji dotyczącej sposobu użycia tego projektu. Czy to coś, co w jakiś sposób żyje z Mongo? To jest biblioteka Java? Czy to tylko sposób myślenia o problemie? Brak pomysłu i żadnych wskazówek. – ftrotter

6

pracowałem za pośrednictwem tego rozwiązania, które pomieścić opublikowany, projekt i wersje historycznych danych:

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

wyjaśnię modelu dalej tutaj: http://software.danielwatrous.com/representing-revision-data-in-mongodb/

dla osób, które zaimplementować coś takiego w Java, oto przykład:

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

Łącznie cały kod, który można widelcem, jeśli chcesz

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

+0

Niesamowite rzeczy :) – Jonathan

12

Oto kolejny rozwiązanie za pomocą jednego dokumentu dla bieżącej wersji i wszystkie stare wersje:

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

data zawiera wszystkie wersje. Macierz data jest zamówiona, nowe wersje otrzymają tylko $push ed na końcu tablicy. data.vid jest identyfikatorem wersji, który jest numerem narastającym.

Pobierz najnowszą wersję:

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

uzyskać konkretną wersję przez vid:

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

Return tylko określonych dziedzinach:

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

Włóż nową wersję: (i zapobiec współbieżne insert/update)

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

2 jest vid obecnej najnowszej wersji i 3 jest nowa wersja dodaje coraz. Ponieważ potrzebujesz najnowszej wersji vid, łatwo jest uzyskać następną wersję: vid: nextVID = oldVID + 1.

Stan zapewnia, że ​​ jest najnowszym vid.

W ten sposób nie ma potrzeby stosowania unikalnego indeksu, ale logika aplikacji musi dbać o zwiększenie numeru vid na wkładce.

usunąć konkretną wersję:

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

to jest to!

(pamiętaj 16MB za granicę dokumentu)

+0

Przy przechowywaniu mmapv1 za każdym razem, gdy do danych dodawana jest nowa wersja, istnieje możliwość przeniesienia dokumentu. – raok1997

+0

Tak, zgadza się. Ale jeśli po prostu dodajesz nowe wersje raz na jakiś czas, powinno to być zaniedbywalne. –

0

Jeśli używasz mangusty, znalazłem następujące wtyczki aby być użytecznym realizacja formacie

mongoose-patch-history

0

Inną opcją na JSON Patch jest użycie wtyczki mongoose-history.

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. 
0

Użyłem pakietu poniżej dla meteor/projektu MongoDB, i to działa dobrze, główną zaletą jest to, że przechowuje historię/rewizje wewnątrz tablicy w tym samym dokumencie, stąd nie ma potrzeby stosowania dodatkowego publikacji lub oprogramowanie pośrednie, aby uzyskać dostęp do historii zmian. Może obsługiwać ograniczoną liczbę wcześniejszych wersji (na przykład dziesięć ostatnich wersji), obsługuje również łączenie zmian (więc wszystkie zmiany dokonane w określonym czasie będą objęte jedną wersją).

nicklozon/meteor-collection-revisions

Inną opcją jest użycie dźwięku Meteor Vermongo (here)

-1

Spróbuj użyć Javers. Dobra biblioteka.

Powiązane problemy