Изменение схемы в RavenDB

Просто ради расширения своих знаний я начал рассматривать различные варианты NoSQL. Первый, который я посетил, это RavenDB, и он выглядит интересно. Я все еще пытаюсь сломать свое глубоко укоренившееся реляционное мышление, наряду с типичными процедурами обслуживания РСУБД.

В моей повседневной работе с Entity Framework мы проходим процедуру написания сценариев изменений БД, обновление модели сопоставления EF и т. д. Как это работает в материалах NoSQL, особенно в RavenDB? После того, как приложение запущено, как можно внести изменения в различные объекты POCO и т. д. и развернуть его в рабочей среде? Что происходит с данными, хранящимися в старых классах POCO?

Я еще не вникал глубоко и не использовал Raven DB в гневе. Это может быть очевидно, как только я это сделаю, но хотелось бы знать заранее, чтобы я не загнал себя в угол.

Спасибо д.


person codedog    schedule 23.01.2011    source источник
comment
Конечно, я что-то упускаю, но IIRC представляет собой базу данных документов без схемы, поэтому единственный разумный ответ — вообще ничего не происходит. Они по-прежнему существуют в том же формате, в котором вы их в поместили...?   -  person Marc Gravell    schedule 24.01.2011
comment
Очень хороший момент... черт возьми, как трудно вырваться из традиционного реляционного пространства!   -  person codedog    schedule 24.01.2011
comment
@codedog Я думаю, что идея не обязательно в том, чтобы выйти из традиционного реляционного пространства, а в том, чтобы понять, что каждый из них представляет собой инструмент с другим набором целей. В нашем приложении мы используем как реляционную базу данных, так и базу данных NoSQL. Одним молотком целый дом не построишь. Точно так же вы не построите дом, используя только пилу.   -  person Brain2000    schedule 10.06.2015


Ответы (4)


Они остаются такими, какие они есть - свойства, которые больше не существуют, будут игнорироваться при загрузке (и теряться при изменении), а отсутствующие свойства возвращаются как нулевые,

Рекомендуется использовать операции на основе наборов, чтобы данные согласовывались с объектной моделью.

О, посмотри на меня, я сейчас за компьютером!

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

Однако важно понимать, что существует разница между отсутствием схемы и отсутствием структуры в том, что все ваши документы содержат свою собственную структуру (пары ключ/значение, обозначающие имя свойства и значение свойства).

Это делает его полезным для всего «просто начинающегося» фактора написания некоторого кода и сохранения ваших данных, но когда так легко изменить структуру вашего кода, может быть сложнее согласовать это с вашими уже сохраненными данными.

На данный момент представляются несколько стратегий:

  • Сделайте свою структуру неизменной, как только вы сохраните данные, версионируйте свои классы
  • Разрешить изменение структуры, но использовать операции на основе набора для обновления данных в соответствии с новой структурой.
  • Разрешить изменение структуры и написать код для устранения несоответствий при загрузке данных.

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

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

  • Используйте свою систему VCS для определения изменений между развернутыми версиями
  • Напишите сценарии миграции, которые обновляются с одной версии на другую.
  • Будьте осторожны с переименованием/удалением свойств - так как загрузка документа и сохранение документа приведет к потере данных, если эти свойства не существуют в новом документе.

И т.п.

Я надеюсь, что это более полезно :-)

person Rob Ashton    schedule 23.01.2011
comment
Я бы дал более полный ответ, но я на телефоне - person Rob Ashton; 24.01.2011
comment
Хотелось бы более полный ответ, но я думаю, что все, что вы, ребята, сказали, прежде чем подвести итог всему. Я просто пытаюсь представить, каково было бы поддерживать веб-сайт со встроенной RavenDB. У меня есть сайт MVC 3 в разработке, в настоящее время использующий EF4. Очень хотелось вырвать DAL и заменить его на RavenDB! - person codedog; 24.01.2011
comment
Вот это да! Это действительно очень подробный ответ! Большое спасибо, что нашли время - это помогло убедить меня сделать решительный шаг. Дадим RavenDB хороший обзор и посмотрим, как он складывается. Мне нужно создать несколько отчетов, но, похоже, с этим помогут индексы. - person codedog; 25.01.2011
comment
Просто помните, что если ваши отчеты становятся слишком сложными, вы всегда можете запустить индексы в СУБД — Raven имеет встроенную поддержку для этого. - person Rob Ashton; 25.01.2011
comment
Я экспериментировал с этим прошлой ночью, точнее с динамической индексацией Raven. Результаты просто потрясающие! Теперь мое мышление переключилось на дизайн документов, который у меня в голове. Я опубликовал новый вопрос об этом. - person codedog; 25.01.2011

RavenDB сериализует ваши объекты .NET в формате JSON. Схемы нет.

Если вы добавите некоторые объекты в свою базу данных, они будут сериализованы. Если вы добавите некоторые свойства к типу, который вы сериализуете, у уже сохраненных вами объектов эти свойства будут отсутствовать.

person driis    schedule 23.01.2011

В этой статье Ayende описывается, как выполнить миграцию с версии 1 на версию 2 (в данном случае изменение свойства «Имя» на свойства «Имя» и «Фамилия»).

http://ayende.com/blog/66563/ravendb-migrations-rolling-updates

В основном слушатель регистрируется в DocumentStore:

documentStore.RegisterListener(new CustomerVersion1ToVersion2Converter())

Пример внедрения взят из упомянутой выше статьи:

public class CustomerVersion1ToVersion2Converter : IDocumentConversionListener
{
    public void EntityToDocument(object entity, RavenJObject document, RavenJObject metadata)
    {
        Customer c = entity as Customer;
        if (c == null)
            return;

        metadata["Customer-Schema-Version"] = 2;
        // preserve the old Name property, for now.
        document["Name"] = c.FirstName + " " + c.LastName;
        document["Email"] = c.CustomerEmail;
    }

    public void DocumentToEntity(object entity, RavenJObject document, RavenJObject metadata)
    {
        Customer c = entity as Customer;
        if (c == null)
            return;
        if (metadata.Value<int>("Customer-Schema-Version") >= 2)
            return;

        c.FirstName = document.Value<string>("Name").Split().First();
        c.LastName = document.Value<string>("Name").Split().Last();
        c.CustomerEmail = document.Value<string>("Email");
    }
}
person Wiebe Tijsma    schedule 18.12.2013

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

Первая часть обработки изменений заключается в том, чтобы убедиться, что вы используете сериализатор, который может обрабатывать отсутствующие/лишние значения. Если поле не определено в данных, установите для него значение null. Если поле в данных не соответствует свойству вашего объекта, игнорируйте его.

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

Для более сложных изменений, таких как переименование/объединение полей или изменение формата данных, добавьте новое поле в свой объект, не удаляя старые, и ваш метод загрузки перенесет данные из старых полей. Когда вы сохраните запись, она будет в новом формате. Этот код можно либо оставить на месте навсегда, обновляя данные по мере необходимости, либо настроить однократный процесс для вызова одного и того же кода для всех существующих объектов. Обратите внимание, что в отличие от скрипта sql для этого типа обновления не требуется время простоя, даже если для запуска большого набора данных требуется много времени, поскольку код может обрабатывать как старые, так и новые форматы.

person Tom Clarkson    schedule 24.01.2011
comment
Вы используете фразу ... чтобы убедиться, что вы используете сериализатор ... Я предполагаю, что ваш совет не относится к RavenDB? В моем ограниченном понимании RavenDB я думал, что у него есть встроенный сериализатор, то есть не то, что мне нужно обрабатывать самому. Разве это не правильно? - person codedog; 24.01.2011
comment
Да, это для общего хранилища документов/объектов NoSQL — я сам в основном использую JSON в Redis. С Raven вы можете указать собственный сериализатор, если вам это нужно, но стандартный позволяет вам устанавливать обязательные/необязательные/игнорируемые поля с помощью атрибутов. - person Tom Clarkson; 24.01.2011