Pull to refresh

Данные в MarkLogic Server [Part1]

Reading time 5 min
Views 2.3K
MarkLogic Server – это документо-ориентированная native XML база данных. Как и в любой документо-ориентированной DB в MarkLogic Server данные можно представить как файлово-фолдерную структуру. Кстати, при доступе к хранилищу через WebDAV данные именно так и представляются. Помимо собственно XML в MarkLogic Server можно хранить и любые бинарные данные в виде файлов.

Внутренне представление XML данных в MarkLogic Server довольно сложное и будет рассмотрено позже. Сейчас же стоит сказать о том, что поместить в MarkLogic Server можно только well formed XML так как хранится он не в виде простого текста, а как объект данных типа XML. Кодировкой внутреннего представления XML данных является Unicode, что избавляет от множества проблем с разными языками. Все Entity в XML данных разворачиваются в цифровые еntity. Если в документе используются только они, то это не доставит никаких проблем, в противном случае MarkLogic Server должен «знать» о всех используемых entity.


Рассмотрим два интересных вопроса – это доступ к документам в MarkLogic Server и наполнение его этими самыми документами.

Далее будем исходить из того, что в базе данных хранятся документы вида
<horse xmlns=”ns1”>
    <location>vacuum</location>
    <geometry>spherical</geometry>
</horse>

И храниться это будет вот так
/horses/
	horse1.xml
	horse2.xml
	…

Для XPath будем использовать префикс ns1=”ns1”

Первым делом рассмотрим способы получения (чтения) XML документов из базы данных в XQuery коде.

Для того чтобы прочитать один документ следует воспользоваться функцией fn:doc вот так
let $id := "horse1"
let $uri := fn:concat("/horses/", $id, ".xml")
return
  fn:doc( $uri )

Указываем путь до документа в качестве параметра и получаем его содержимое
fn:doc(
   [$uri as xs:string*]
) as document-node()*

Результатом этой функции является корневой элемент (тег) для XML документа document(), text() элемент для текстового документа и binary() элемент для бинарных документов.

К XML результату этой функции можно применять любой XPath. Например так
fn:doc( $uri )/ns1:horse

или получить список тегов ns1:location
fn:doc( $uri )/ns1:horse/ns1:location

или сделать это так
fn:doc( $uri )//ns1:location


Документы в MarkLogic Server можно объединять в логические группы сохраняя их в разные директории. Например документы (объекты) “horseN.xml” сохранены в директории “/horses/”. Но! Довольно часто требуется создавать пересекающиеся группы (объединения) документов. Для этих целей, а так же для ускорения доступа к документам в MarkLogic Server существует механизм коллекций. Каждый документ может состоять в нескольких коллекциях одновременно, никаких ограничений на это не существует.

Далее рассмотрим способ получения документов из коллекции. Предположим, что наши документы включены в коллекцию “horses-collection”, тогда доступ к коллекции выполняется следующим образом
let $collections := ("horses-collection")
return
    fn:collection($collections)

где $collections – это список коллекций документы которых нужно получить
fn:collection(
   [$uri as xs:string*]
) as document-node()*

Данная функция возвращает документы включенные в указанные коллекции. Результатом fn:collection является список документов.

Параметр $uri в функции fn:collection не обязателен. При его отсутствии fn:collection возвращает список всех документов в базе данных. Следующее выражение позволяет сделать это
fn:collection()

Стоит заметить, что коллекции в MarkLogic Server не нужно создавать или конфигурировать зарaнее. При добавлении документа в несуществующую коллекцию она создается вместе с ним и документ помещается во вновь созданную коллекцию. Такой подход позволяет создавать коллекции динамически. Это дает еще больше гибкости при организации быстрого доступа к документам в хранилище.

Существует еще один способ доступа к документам, добавленный разработчиками для упрощения кода программ на XQuery
/ns1:horse

данное выражение эквивалентно следующему
fn:collection()/ns1:horse

То есть сканировать все документы в хранилище и вернуть содержимое документов, которые имеют корневой тег ns1:horse.

Получается что в коде XQuery можно писать XPath как отбельный элемент и он будет применен ко всем документам хранилища и вернет результат своего выполнения.

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

Результатом следующего выражения будут все тот же список документов ns1:horse, но при его выполнении будет просканирован каждый тег в базе, что является очень ресурсоемкой задачей
//ns1:horse

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

Иногда документы сохраняют в одну директорию не объединяя их в коллекцию. Но при этом расположение документов внутри одной директории имеет смысл в логике программы и требует выполнять доступ к этим документам как к единой сущности. Для выполнения такой задачи можно воспользоватся следующим методом
xdmp:directory("/horses /", "1")/ns1:horse

Функция xdmp:directory возвращает все документы в указанной директории
xdmp:directory(
   $uri as xs:string*,
   [$depth as xs:string?]
) as document-node()*

Здесь необязательная переменная может принимать два значения “1” и “infinity” описывает же оно глубину вложенности документов, которые войдут в результат. В случае $depth=“1” MarkLogic Server ограничится документами в указанной директории, “infinity” же заставит его сканировать все поддиректории в поисках документов.

Все приведенные выше XPath выражения простые, но на их месте может быть что-то похожее на это
//ns1:location[ (fn:starts-with(., “va”) and  fn:starts-with(., “m”)) or (. eq “location1”) ]

Сложный XPath сильно увеличивает затрачиваемые на выполнение запроса ресурсы. Организовывать получение документов из базы данных лучше средствами самой DB такими как коллекции и директории используя при необходимости простые XPath выражение.

Второй важный вопрос — это наполнение базы. Сразу оговорюсь, что MarkLogic Server не поддерживает XQuery Update расширение для XQuery и предоставляет функции манипулирования документами через свой API.

Наполнение базы данных можно осуществить несколькими способами:

1. Создать документ прямо из XQuery кода. Делается это примерно так
declare variable $collections := ("horses");
let $uri := “/horses/horse1.xml”
let $horse := 
    <horse xmlns=”ns1”>
        <location>vacuum</location>
        <geometry>spherical</geometry>
    </horse>
return
    xdmp:document-insert( $uri, $horse, xdmp:default-permissions(), $collections )

Параметры функции xdmp:document-insert выглядят так
xdmp:document-insert(
   $uri as xs:string,
   $root as node(),
   [$permissions as element(sec:permission)*],
   [$collections as xs:string*],
   [$quality as xs:int?],
   [$forest-ids as xs:unsignedLong*]
) as empty-sequence()

где $uri – это адрес документа относительно корня хранилища. В настройках базы данных MarkLogic Server существует возможность включить автоматическое создание директорий и тогда $uri может ссылаться на несуществующую директорию и она будет создана при создании документа.
$root — тело документа
$permissions – настройки доступа документа
$collections – список коллекций в которые должен быть включен документ.

2. Загрузить данные через WebDAV. Этот способ подходит для загрузки довольно больших объёмов данных в хранилище. Для доступа через WebDAV в MarkLogic Server должен быть создан соответствующий (WebDAV) application server для базы данных к которой необходимо получить доступ.

3. Для больших объемов данных или очень специфичных задач можно воспользоваться java утилитой, RecordLoader предназначенной для загрузки документов в MarkLogic Server.

4. AutoLoader это еще одна полезная утилита, позволяющая отслеживать изменения на файловой системе и автоматически загружать документы в MarkLogic Server. Для загрузки используется утилита RecordLoader.
Tags:
Hubs:
+4
Comments 2
Comments Comments 2

Articles