Czy możesz podzielić się swoimi przemyśleniami, jak zaimplementować przechowywanie wersji danych w MongoDB. (Zadałem podobne pytanie dotyczące Cassandry . Jeśli masz jakieś przemyślenia, która db jest lepsza, proszę podziel się)
Załóżmy, że muszę zaktualizować rekordy w prostej książce adresowej. (Rekordy książki adresowej są przechowywane jako płaskie obiekty Json). Oczekuję, że historia:
- będą używane rzadko
- zostaną wykorzystane naraz, aby przedstawić go w sposób „maszyny czasu”
- na jeden rekord nie będzie więcej niż kilkaset wersji. historia nie wygasa.
Rozważam następujące podejścia:
Utwórz nową kolekcję obiektów do przechowywania historii rekordów lub zmian w rekordach. Będzie przechowywać jeden obiekt na wersję z odniesieniem do pozycji książki adresowej. Takie zapisy wyglądałyby następująco:
{ „_id”: „nowy identyfikator”, „użytkownik”: identyfikator_użytkownika, „timestamp”: timestamp, „address_book_id”: „identyfikator rekordu książki adresowej” „old_record”: {„first_name”: „Jon”, „last_name”: „Doe” ...} }
To podejście można zmodyfikować, aby przechowywać tablicę wersji na dokument. Ale wydaje się, że jest to wolniejsze podejście bez żadnych korzyści.
Przechowuj wersje jako obiekt serializowany (JSON) dołączony do pozycji książki adresowej. Nie jestem pewien, jak dołączyć takie obiekty do dokumentów MongoDB. Być może jako tablica ciągów. ( Modelowane na podstawie prostej wersji dokumentów za pomocą CouchDB )
źródło
Odpowiedzi:
Pierwszym ważnym pytaniem podczas nurkowania jest „jak chcesz przechowywać zestawy zmian” ?
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ć innej kolekcji, aby zaoszczędzić miejsce w pamięci. Zwykle nie potrzebujesz pełnej historii dla prostego zapytania. Tak więc, utrzymując historię poza obiektem, możesz również trzymać ją poza pamięcią, do której często uzyskiwany jest dostęp, gdy dane są sprawdzane.
Aby ułatwić moje życie, stworzyłbym dokument historyczny zawierający słownik różnic znaczników czasu. Coś takiego:
Aby moje życie było naprawdę łatwe, uczyniłbym tę część moich obiektów DataObject (EntityWrapper, cokolwiek), których używam do uzyskiwania dostępu do moich danych. Zasadniczo obiekty te mają pewną formę historii, dzięki czemu można łatwo zastąpić
save()
metodę, aby wprowadzić tę zmianę w tym samym czasie.AKTUALIZACJA: 2015-10
Wygląda na to, że istnieje teraz specyfikacja do obsługi różnic JSON . To wydaje się być bardziej niezawodnym sposobem przechowywania różnic / zmian.
źródło
changes
jest naprawdę łatwe:db.hist.update({_id: ID}, {$set { changes.12345 : CHANGES } }, true)
wykona wstawkę, która zmieni tylko wymagane dane. Mongo tworzy dokumenty z „przestrzenią buforową” do obsługi tego rodzaju zmian. Obserwuje również, jak zmieniają się dokumenty w kolekcji i modyfikuje rozmiar bufora dla każdej kolekcji. Tak więc MongoDB jest przeznaczony do dokładnie tego rodzaju zmian (dodaj nową właściwość / push do tablicy).Istnieje schemat kontroli wersji o nazwie „Vermongo”, który dotyczy niektórych aspektów, które nie zostały omówione w innych odpowiedziach.
Jednym z tych problemów są jednoczesne aktualizacje, drugim jest usuwanie dokumentów.
Vermongo przechowuje kompletne kopie dokumentów w kolekcji cieni. W niektórych przypadkach może to powodować zbyt duże obciążenie, ale myślę, że upraszcza to również wiele rzeczy.
https://github.com/thiloplanz/v7files/wiki/Vermongo
źródło
Oto inne rozwiązanie wykorzystujące jeden dokument dla bieżącej wersji i wszystkich starych wersji:
data
zawiera wszystkie wersje.data
Tablica jest uporządkowane , nowe wersje dostanie tylko$push
ed do końca tablicy.data.vid
to identyfikator wersji, który jest liczbą rosnącą.Pobierz najnowszą wersję:
Uzyskaj konkretną wersję przez
vid
:Zwróć tylko określone pola:
Wstaw nową wersję: (i zapobiegaj jednoczesnemu wstawianiu / aktualizacji)
2
jestvid
bieżącą najnowszą wersją i3
jest wstawiana nowa wersja. Bo trzeba najnowsza wersja użytkownikavid
, jest to łatwe do zrobienia dostać kolejna wersja navid
:nextVID = oldVID + 1
.$and
Warunek zapewni, że2
jest ostatnivid
.W ten sposób nie ma potrzeby tworzenia unikalnego indeksu, ale logika aplikacji musi zadbać o zwiększenie
vid
wkładki.Usuń określoną wersję:
Otóż to!
(pamiętaj limit 16 MB na dokument)
źródło
Jeśli szukasz gotowego rozwiązania -
Mongoid ma wbudowaną prostą wersję
http://mongoid.org/en/mongoid/docs/extras.html#versioning
mongoid-history to wtyczka Ruby, która zapewnia znacznie bardziej skomplikowane rozwiązanie z inspekcją, cofaniem i ponawianiem
https://github.com/aq1018/mongoid-history
źródło
Pracowałem nad tym rozwiązaniem, które obejmuje opublikowane, szkice i historyczne wersje danych:
Wyjaśnię ten model tutaj: http://software.danielwatrous.com/representing-revision-data-in-mongodb/
Dla tych, którzy mogą implementować coś takiego w Javie , oto przykład:
http://software.danielwatrous.com/using-java-to-work-with-versoted-data/
W tym cały kod, który możesz rozwidlić, jeśli chcesz
https://github.com/dwatrous/mongodb-revision-objects
źródło
Jeśli używasz mangusty, znalazłem następującą wtyczkę, która jest przydatną implementacją formatu łatki JSON
mongoose-patch-history
źródło
Inną opcją jest użycie wtyczki mongoose-history .
źródło
Użyłem poniższego pakietu do projektu Mete / MongoDB i działa dobrze, główną zaletą jest to, że przechowuje historię / zmiany w tablicy w tym samym dokumencie, dlatego nie ma potrzeby dodatkowych publikacji lub oprogramowania pośredniego, aby uzyskać dostęp do historii zmian . Może obsługiwać ograniczoną liczbę poprzednich wersji (np. Ostatnich dziesięciu wersji), obsługuje także konkatenację zmian (więc wszystkie zmiany dokonane w określonym okresie zostaną objęte jedną wersją).
wersje nicklozon / meteor-collection-rewizje
Inną opcją dźwiękową jest użycie Meteor Vermongo ( tutaj )
źródło