Вопрос

Можете ли вы поделиться своими мыслями, как бы вы внедрили данные версий данных в MongoDB. (Я спросил Подобный вопрос, касающийся Кассандры. Анкет Если у вас есть какие -либо мысли, какой БД лучше для этого, пожалуйста, поделитесь)

Предположим, что мне нужно вернуть записи в простой адресной книге. (Адресные книги записей хранятся в виде объектов Flat JSON). Я ожидаю, что история:

  • будет использоваться нечасто
  • будет использоваться все сразу, чтобы представить его в моде "Time"
  • В версиях не будет больше, чем несколько сотен до одной записи. История не истекает.

Я рассматриваю следующие подходы:

  • Создайте новую коллекцию объектов для хранения истории записей или изменений в записях. Он хранит один объект на версию со ссылкой на запись адресной книги. Такие записи будут выглядеть следующим образом:

    {
     '_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)

Это было полезно?

Решение

Первый большой вопрос при погружении в это - это «Как вы хотите хранить изменения»?

  1. Разницы?
  2. Целые копии записей?

Мой личный подход - хранить различия. Поскольку отображение этих различий на самом деле является особым действием, я бы поместил различия в другую коллекцию «истории».

Я бы использовал другую коллекцию, чтобы сохранить пространство памяти. Как правило, вы не хотите полной истории для простого запроса. Таким образом, не позволяя истории в стороне от объекта, вы также можете не допустить ее в обычно доступной памяти, когда эти данные запрашиваются.

Чтобы сделать мою жизнь легкой, я бы сделал исторический документ, содержащий словарь разбитых времени различий. Что-то вроде этого:

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

Чтобы сделать мою жизнь очень легкой, я бы сделал эту часть своих данных данных (EntityWrapper, что угодно), которую я использую для доступа к своим данным. Как правило, эти объекты имеют некоторую форму истории, так что вы можете легко переопределить save() Метод, чтобы внести это изменение одновременно.

Обновление: 2015-10

Похоже, сейчас Спецификация для обработки различий JSON. Анкет Это кажется более надежным способом хранения различий / изменений.

Другие советы

Существует схема управления версиями под названием «Вермонго», которая рассматривает некоторые аспекты, с которыми не рассматривались в других ответах.

Одним из этих вопросов является одновременное обновления, еще один из них удаляет документы.

Вермонго хранит комплексные копии документов в коллекции Shadow. Для некоторых вариантов использования это может вызвать слишком много накладных расходов, но я думаю, что это также упрощает много вещей.

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

Вот еще одно решение, используя один документ для текущей версии и всех старых версий:

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

data содержит все версии. А data массив есть упорядоченный, новые версии только получат $pushЭд до конца массива. 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

Монгоидная гистория-это плагин Ruby, который обеспечивает значительно более сложное решение с аудитом, отменой и повторной

https://github.com/aq1018/mongoid-history

Я проработал это решение, которое вмещает опубликованный, проект и исторические версии данных:

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

Я объясняю модель дальше здесь: http://software.danielwatrous.com/representing-revision-data-in-mongodb/

Для тех, кто может реализовать что -то подобное в Ява, вот пример:

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

В том числе весь код, который вы можете расколоть, если хотите

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

Если вы используете Mongoose, я обнаружил, что следующий плагин является полезной реализацией 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, и он работает хорошо, основное преимущество заключается в том, что он хранит историю/пересмотр в массиве в том же документе, поэтому не нужно дополнительные публикации или промежуточное программное обеспечение для доступа Анкет Он может поддерживать ограниченное количество предыдущих версий (например, последние десять версий), также поддерживает конкатенацию изменений (поэтому все изменения произошли в течение определенного периода, будут покрыты одним редакцией).

Niclozon/Meteor-Collection-Revisions

Другой вариант звука - использовать Meteor vermongo (здесь)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top