Microsoft DocumentDB: статья вторая, ресурсы и концепции

в 4:33, , рубрики: json, Microsoft Azure, rdbms, Блог компании Microsoft, облако, хорошая база данных

Как уже было сказано в первой статье, DocumentDB выставляет доступ к своей функциональности в виде программной модели RESTful, и сущности, хранящиеся внутри базы, называются ресурсами, и адресуются по URI. Для доступа к этим ресурсам можно использовать стандартные HTTP verbs, хэдеры и коды статусов.
Пока мы готовим годный пример про DocumentDB (дело небыстрое и вдумчивое) и ответы на ваши вопросы к первой статье, предлагаем почитать немного подробнее про ресурсы и концепции, на которых работает DocumentDB.
Microsoft DocumentDB: статья вторая, ресурсы и концепции

Microsoft DocumentDB: статья вторая, ресурсы и концепции

Ресурсная модель DocumentDB состоит из набора ресурсов, хранящихся в определенной структуре внутри аккаунта, и каждый из них доступен по постоянному URI. Итак, все начинается с аккаунта DocumentDB. Аккаунт — логический контейнер, в котором хранятся базы, каждая из которых содержит коллекции, которые, в свою очередь, содержат хранимые процедуры, триггеры, UDF и др. У каждой базы есть пользователи, имеющие набор прав на манипуляции с документами. Разрешения выглядят в виде токенов, коллекции — это контейнеры JSON-документов и логики на JS.

Системные ресурсы — аккаунты, базы, коллекции, пользователи, хранимые процедуры, триггеры и UDF — имеют фиксированную схему, документы и аттачменты же ограничений на схему не имеют и, соответственно, называются пользовательскими ресурсами. Ресурсы обоих типов описываются JSON.

Microsoft DocumentDB: статья вторая, ресурсы и концепции

Каждый аккаунт, которых может быть много внутри одной подписки Azure, это сборный контейнер, состоящий из юнитов, объединяющих в себе SSD-хранилище и зафиксированный показатель пропускной способности. Юниты можно в любой момент добавлять или убирать. Создать и изменять настройки аккаунта можно на портале управления Microsoft Azure — portal.azure.com/ — либо с помощью REST API (добрая часть функциональности платформы выставлена для управления по REST API).
Если аккаунт — логический контейнер высшего уровня, то база данных — это контейнер для коллекций и пользователь. Внутри аккаунта может быть сколько угодно баз данных.

Microsoft DocumentDB: статья вторая, ресурсы и концепции

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

Коллекция — контейнер следующего уровня вложенности, уже для документов JSON. Коллекция как контейнер служит не только для объединения, но и как юнит масштабирования — транзакций и запросов. Самый простой способ масштабирования — добавить больше коллекций и распределить по ним SSD-хранилище. Автоматическое же масштабирование уже работает — коллекция автоматически меняет свой размер по мере добавления или удаления документов. Пока DocumentDB в превью и имеет только один режим работы (Standard Preview), максимальный размер, до которого можно масштабироваться коллекции, равен 10 Гб.

Автоматическая индексация

DocumentDB вообще не требует от вас планирования схемы для системы. Документы не подразумевают ее наличия и, как только вы добавляете их в коллекцию, DocumentDB автоматически индексирует их (=> можно выполнять запросы). Автоматическое индексирование документов без необходимости думать о схеме и вторичных индексах — это одна из главных фишек DocumentDB. При этом обеспечивается стабильно-устойчивое количество очень быстрых операций записи при последовательных запросах.
Автоматическую индексацию можно немного править, выбирая политику индексации и, таким образом, выигрывая на производительности и хранилище. Можно либо вообще отключить автоматическую индексацию, либо выбрать только некоторые документы, которые будут индексироваться (и выбрать, которые НЕ будут индексироваться) и выбрать между синхронным (consistent) и асинхронным (lazy) режимами (по умолчанию индекс обновляется синхронным образом на каждой операции Insert, Replace или Delete, это поведение можно подкорректировать на «ленивый» режим и, возможно, получить некую выгоду в производительности при, например, коллекциях с большим количеством операций чтения).

Мультидокументные транзакции

В RDBMS обычно пишут бизнес-логику с использованием хранимых процедур и триггеров, запуская в виде транзакции, что накладывает на разработчика необходимость знания двух разных языков разработки — языка разработки проекта приложения (JS, Python, др.) и T-SQL. В DocumentDB же доступна программная модель исполнения JS для коллекций в виде хранимых процедур и триггеров, что позволяет выполнять эффективный контроль параллелизма, индексирование и не отвлекаться на обилие прикладных средств.
DocumentDB самостоятельно оборачивает эту логику в Ambient ACID транзакцию со snapshot isolation и, если в процессе JS выкидывает исключение, то вся транзакция откатывается. Исполнение JS проходит внутри движка в том же адресном пространстве, что и Buffer Pool, что хорошо сказывается на производительности.

function businessLogic(name, author) {
    var context = getContext();
    var collectionManager = context.getCollection();        
    var collectionLink = collectionManager.getSelfLink()
// создаем документ.
    collectionManager.createDocument(collectionLink,
        {id: name, author: author},
        function(err, documentCreated) {
            if(err) throw new Error(err.message);
// фильтруем документы по автору
            var filterQuery = "SELECT * from root r WHERE r.author = 'George R.'";
            collectionManager.queryDocuments(collectionLink,
                filterQuery,
                function(err, matchingDocuments) {
                    if(err) throw new Error(err.message);
context.getResponse().setBody(matchingDocuments.length);
// заменяем автора
                    for (var i = 0; i < matchingDocuments.length; i++) {
                        matchingDocuments[i].author = "George R. R. Martin";
                        // we don’t need to execute a callback because they are in parallel
                        collectionManager.replaceDocument(matchingDocuments[i]._self,
                            matchingDocuments[i]);   
                    }
                })
        })
};

Все это успешно заворачивается в транзакционное выполнение через HTTP POST.

client.createStoredProcedureAsync(collection._self, {id: "CRUDProc", body: businessLogic})
   .then(function(createdStoredProcedure) {
        return client.executeStoredProcedureAsync(createdStoredProcedure.resource._self,
            "NoSQL Distilled",
            "Martin Fowler");
    })
    .then(function(result) {
        console.log(result);
    },
    function(error) {
        console.log(error);
    });

JSON и JS наш герой понимает из коробки, поэтому никаких проблем с типами не происходит. Подробнее - Azure DocumentDB REST APIs .
 

Хранимые процедуры, триггеры и UDF

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

Зарегистрировать на выполнение процедуру, триггер и UDF можно с помощью REST API, и после регистрации хранимая процедура, триггер или UDF предварительно компилируются и хранятся как байт-код, который запускается на выполнение.

Регистрация хранимых процедур

Регистрация хранимой процедуры = создание ресурса для новой процедуры и присваивание ее коллекции с HTTP POST.

var storedProc = {
    id: "validateAndCreate",
    body: function (documentToCreate) {
        documentToCreate.id = documentToCreate.id.toUpperCase();
var collectionManager = getContext().getCollection();
        collectionManager.createDocument(collectionManager.getSelfLink(),
            documentToCreate,
            function(err, documentCreated) {
                if(err) throw new Error('Error while creating document: ' + err.message;
                getContext().getResponse().setBody('success - created ' + 
                        documentCreated.name);
            });
    }
};
client.createStoredProcedureAsync(collection._self, storedProc)
    .then(function (createdStoredProcedure) {
        console.log("Successfully created stored procedure");
    }, function(error) {
        console.log("Error");
    });

 

Исполнение хранимой процедуры

Исполнение хранимой процедуры делается опять же с HTTP POST с передачей нужных параметров в теле запроса.

var inputDocument = {id : "document1", author: "G. G. Marquez"};
client.executeStoredProcedureAsync(createdStoredProcedure.resource._self, inputDocument)
    .then(function(executionResult) {
        assert.equal(executionResult, "success - created DOCUMENT1");
    }, function(error) {
        console.log("Error");
    });

Регистрация триггеров

Регистрация триггера = создание нового ресурса для коллекции с HTTP POST, и в процессе можно указать, будет ли триггер вызываться до или после и тип выполняемой операции (CRUD).

var preTrigger = {
    id: "upperCaseId",
    body: function() {
            var item = getContext().getRequest().getBody();
            item.id = item.id.toUpperCase();
            getContext().getRequest().setBody(item);
    },
    triggerType: TriggerType.Pre,
    triggerOperation: TriggerOperation.All
}
client.createTriggerAsync(collection._self, preTrigger)
    .then(function (createdPreTrigger) {
        console.log("Successfully created trigger");
    }, function(error) {
        console.log("Error");
    });

Убрать регистрацию триггера можно, выполнив HTTP DELETE на ресурс триггера.

client.deleteTriggerAsync(createdPreTrigger._self);
    .then(function(response) {
        return;
    }, function(error) {
        console.log("Error");
    });

Аттачменты

В DocumentDB можно хранить бинарные файлы (блобы), которые выглядят как специальные сущности — аттачменты. Аттачмент — это специальный документ (JSON), который ссылается на реальный файл. Например:
Содержимое какой-то книги лежит в хранилище в DocumentDB либо любом другом.
Приложение может хранить метаданные каждого пользователя в виде отдельного документа — например, Alex для book1 будет доступен по ссылке /colls/alex/docs/book1.
Аттачменты указывает на страницы книги, то есть /colls/alex/docs/book1/chapter1, chapter2 и т.д.

Резюме

В этой вводной статье мы рассмотрели совсем базовые принципы и концепции DocumentDB. Сервис новый, поэтому мы сами его активно изучаем и надеемся, что скоро мы сможем представить какой-нибудь красивый пример использования. Оставайтесь на связи :)

Полезные ссылки

Попробовать Azure бесплатно на 30 дней!
Изучить курсы виртуальной академии Microsoft по облачным и другим технологиям
Загрузить бесплатную или пробную Visual Studio
Центр разработки Microsoft Azure (azurehub.ru) – сценарии, руководства, примеры, рекомендации по выбору сервисов и разработке
Twitter.com/windowsazure_ru — последние новости Microsoft Azure
Сообществе Microsoft Azure на Facebook – эксперты, вопросы
Стать разработчиком универсальных приложений Windows

Автор: ahriman

Источник

Поделиться

* - обязательные к заполнению поля