Способы реализации управления версиями данных в MongoDB
можете ли вы поделиться своими мыслями, как бы вы реализовали управление версиями данных в MongoDB. (Я спросил аналогичный вопрос относительно Кассандры. Если у вас есть какие-либо мысли, которые db лучше для этого, пожалуйста, поделитесь)
предположим, что мне нужны записи версий в простой адресной книге. (Записи адресной книги хранятся как плоские объекты json). Я ожидаю, что история:
- будет использоваться нечасто
- будет использоваться все сразу, чтобы представить его в стиле "Машины времени"!--9-->
- не будет больше версий, чем несколько сотен в одну запись. история не заканчивается.
Я рассматриваю следующие подходы:
-
создайте новую коллекцию объектов для хранения истории записей или изменений записей. Он будет хранить один объект на версию со ссылкой на запись адресной книги. Такие записи выглядели бы следующим образом:
{ '_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' ...} }
этот подход можно изменить для хранения массива версий на документ. Но это, кажется, медленный подход без каких-либо преимуществ.
хранить версии как сериализованный объект (JSON), прикрепленный к записям адресной книги. Я не уверен, как прикрепить такие объекты к документам MongoDB. Возможно, как массив строк. (по аналогии с простой документ версионность на CouchDB)
9 ответов
первый большой вопрос при погружении в это "как вы хотите хранить наборы изменений"?
- диффов?
- все записи копии?
мой личный подход состоял бы в том, чтобы хранить различия. Поскольку отображение этих различий действительно является специальным действием, я бы поместил различия в другую коллекцию "история".
Я бы использовал другую коллекцию для экономии места в памяти. Вам обычно не нужна полная история для простой запрос. Таким образом, сохраняя историю из объекта, вы также можете сохранить ее из общедоступной памяти при запросе этих данных.
чтобы сделать мою жизнь легкой, я бы сделал исторический документ, содержащий словарь временных меток различий. Что-то вроде этого:--5-->
{
_id : "id of address book record",
changes : {
1234567 : { "city" : "Omaha", "state" : "Nebraska" },
1234568 : { "city" : "Kansas City", "state" : "Missouri" }
}
}
чтобы сделать мою жизнь действительно легкой, я бы сделал эту часть моих DataObjects (EntityWrapper, что угодно), которые я использую для доступа к моим данным. Как правило, эти объекты имеют некоторую форму истории, так что вы может легко переопределить save()
способ, чтобы сделать это изменение в то же время.
обновление: 2015-10
похоже, что теперь есть спецификация для обработки различий JSON. Это кажется более надежным способом хранения различий / изменений.
существует схема управления версиями под названием "Вермонго", которая затрагивает некоторые аспекты, которые не рассматривались в других ответах.
одна из этих проблем-одновременное обновление, другая-удаление документов.
Vermongo хранит полные копии документов в теневой коллекции. Для некоторых случаев использования это может вызвать слишком много накладных расходов, но я думаю, что это также упрощает многие вещи.
вот еще одно решение, использующее один документ для текущей версии и всех старых версий:
{
_id: ObjectId("..."),
data: [
{ vid: 1, content: "foo" },
{ vid: 2, content: "bar" }
]
}
data
содержит все версий. The data
массив приказал новые версии только $push
ed до конца массива. data.vid
- это идентификатор версии, порядкового номера.
получить самую последнюю версию:
find(
{ "_id":ObjectId("...") },
{ "data":{ $slice:-1 } }
)
получить конкретную версию по vid
:
find(
{ "_id":ObjectId("...") },
{ "data":{ $elemMatch:{ "vid":1 } } }
)
возврат только указанных полей:
find(
{ "_id":ObjectId("...") },
{ "data":{ $elemMatch:{ "vid":1 } }, "data.content":1 }
)
вставить новую версию: (и предотвратить одновременную вставку/обновление)
update(
{
"_id":ObjectId("..."),
$and:[
{ "data.vid":{ $not:{ $gt:2 } } },
{ "data.vid":2 }
]
},
{ $push:{ "data":{ "vid":3, "content":"baz" } } }
)
2
- это vid
текущей последней версии и 3
вставляется новая версия. Потому что вам нужна самая последняя версия vid
, это легко сделать, чтобы получить следующую версию vid
: nextVID = oldVID + 1
.
на $and
условие обеспечит, что 2
последний vid
.
таким образом, нет необходимости в уникальном индексе, но логика приложения должна заботиться о приращении vid
вставить.
удалить определенную версию:
update(
{ "_id":ObjectId("...") },
{ $pull:{ "data":{ "vid":2 } } }
)
вот именно!
(помните ограничение 16 Мб на документ)
Если вы ищете готовое к рулону решение -
Mongoid имеет встроенную простую версию
http://mongoid.org/en/mongoid/docs/extras.html#versioning
mongoid-history-это плагин Ruby, который предоставляет значительно более сложное решение с аудитом, отменой и повтором
Я работал через это решение, которое вмещает опубликованные, черновики и исторические версии данных:
{
published: {},
draft: {},
history: {
"1" : {
metadata: <value>,
document: {}
},
...
}
}
Я объясняю модель дальше здесь:http://software.danielwatrous.com/representing-revision-data-in-mongodb/
для тех, кто может реализовать что-то вроде этого в Java, вот пример:
http://software.danielwatrous.com/using-java-to-work-with-versioned-data/
включая весь код, который вы можете развить, если хотите
Если вы используете мангуста, я нашел следующий плагин, чтобы быть полезной реализацией JSON Patch
другой вариант-использовать Мангуст-история плагин.
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.
Я использовал приведенный ниже пакет для проекта meteor/MongoDB, и он работает хорошо, основное преимущество заключается в том, что он хранит историю / ревизии в массиве в том же документе, следовательно, нет необходимости в дополнительных публикациях или промежуточном ПО для доступа к истории изменений. Он может поддерживать ограниченное количество предыдущих версий (ex. последние десять версий), он также поддерживает изменение-конкатенацию (поэтому все изменения, произошедшие в течение определенного периода, будут покрыты одним пересмотр.)
никлозон / Метеор-коллекция-редакции
другой звуковой вариант - использовать Meteor Vermongo (здесь)