Введение в ArangoDB

ArangoDB — многоцелевая СУБД с открытым исходным кодом с гибкими моделями хранения данных для документов, графов и данных типа ключ-значение. СУБД предназначена для построения высокопроизводительных приложений с использование удобного SQL-подобного языка запросов или расширений на JavaScript. ArangoDB предоставляет возможности: ACID-транзакции, масштабирование по горизонтали или вертикали в несколько кликов.

Ключевые особенности

  • Отсутствие необходимости определения схемы хранения данных (Schema-free), данные структурируются в форме документов, в которых метаданные и информация о структуре отделена от пользовательских данных;
  • Возможность использования ArangoDB в качестве сервера для web-приложений. Поддержка доступа к базе через REST/Web API;
  • Использование JavaScript на стороне базы данных;
  • Многопоточная архитектура, распределяющая нагрузку на все ядра CPU;
  • Гибкая модель хранения данных, в которой могут быть комбинированы пары ключ-значение, документы и параметры, определяющие связи между записями (предоставляются средства для обхода вершин графа);
  • Возможность выбора типа индекса, соответствующего решаемым задачам (например, можно использовать индекс для полнотекстового поиска);
  • Настраиваемая надежность: приложение само может определять, что для него важнее: более высокая надёжность или более высокая производительность;
  • Эффективное хранилище, в котором в полной мере используются возможности современного оборудования (например, SSD-накопители) и могут применяться большие кэши;
  • Транзакции: возможность запускать запросы сразу для нескольких документов или коллекций с опциональной согласованностью транзакций и изоляцией;
  • Поддержка репликации и шардинга: возможность создания master-slave конфигураций и разнесения наборов данных на разные серверы в зависимости от определённого признака.
  • Поддержка конструкций ECMAScript 6, таких как итераторы, тип symbol, типизированные массивы, списки (sets) и хэши (maps)

Структура данных

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

Язык запросов

В качестве языка запросов ArangoDB использует специально разработанный язык запросов AQL (ArangoDB Query Language).  Простейший запрос на получение документа имеет виду

RETURN DOCUMENT("users/9883")

В результате выполнения которого будет получен ответ вида:

[
  {
    "_key": "9883",
    "_id": "users/9883",
    "_rev": "9883",
    "age": 32,
    "name": "John Smith"
  }
]

Для выполнения тестовых запросов можно воспользоваться пользовательским интерфейсом ArangoDB, которой обычно доступен на 8529  порту. В указанном выше запросе используется функция DOCUMENT, которая используется для возврата одного или нескольких документов. В данных ответа помимо обычных атрибутов присутствуют и системные _id, _key и _rev.

Для добавления нового документа в коллекцию users выполняем запрос

INSERT { name: "Katie Foster", age: 27 } INTO users

В данном запросе фигурные скобки используются для обозначения документа (объекта). Более тогда объекты могут иметь вложенную структуру. Например такую:

{
  "name": {
    "first": "Katie",
    "last": "Foster"
  }
}

Если нужно добавить документ и сразу получить результат, то выполните запрос

INSERT { name: "Katie Foster", age: 27 } INTO users RETURN NEW

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

RETURN DOCUMENT( ["users/9883", "users/9915", "users/10074"] )

Либо можно использовать цикл for

FOR user IN users RETURN user

Этот цикл вернет все документы из коллекции users. Результатом будет массив объектов:

[
  {
    "_key": "9915",
    "_id": "users/9915",
    "_rev": "9915",
    "age": 27,
    "name": "Katie Foster"
  },
  {
    "_key": "9883",
    "_id": "users/9883",
    "_rev": "9883",
    "age": 32,
    "name": "John Smith"
  },
  {
    "_key": "10074",
    "_id": "users/10074",
    "_rev": "10074",
    "age": 69,
    "name": "James Hendrix"
  }
]

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

FOR user IN users
  SORT user.age DESC
  RETURN user

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

FOR user IN users
  FILTER user.age > 30
  SORT user.age
  RETURN user

Для модификация конкретного поля документа используется инструкция UPDATE, которая обновляет значение указанных ключей документа, а остальные оставляя без изменения:

UPDATE "9915" WITH { age: 40 } IN users RETURN NEW

Здесь "9915" - значения ключа документа (поле _key). Если нужно заменить указанный документ целиком, тогда используется инструкция REPLACE, синтаксис которой аналогичен синтаксису UPDATE.

В ArangoDB есть возможность возврата документов не целиком, а только необходимого подмножества атрибутов, с точки зрения AQL - это запишется так:

FOR user IN users 
  RETURN { userName: user.name, age: user.age }

Также возможно вычислять возвращаемые значения:

FOR user IN users
  RETURN CONCAT(user.name, "'s age is ", user.age)

В результате получим:

[
  "James Hendrix's age is 69",
  "John Smith's age is 32",
  "Katie Foster's age is 40"
]

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

FOR user1 IN users
  FOR user2 IN users
    FILTER user1 != user2
    RETURN {
        pair: [user1.name, user2.name],
        sumOfAges: user1.age + user2.age
    }

Имеем результат:

[
  {
    "pair": [ "James Hendrix", "John Smith" ],
    "sumOfAges": 101
  },
  {
    "pair": [ "James Hendrix", "Katie Foster" ],
    "sumOfAges": 109
  },
  {
    "pair": [ "John Smith", "James Hendrix" ],
    "sumOfAges": 101
  },
  {
    "pair": [ "John Smith", "Katie Foster" ],
    "sumOfAges": 72
  },
  {
    "pair": [ "Katie Foster", "James Hendrix" ],
    "sumOfAges": 109
  },
  {
    "pair": [ "Katie Foster", "John Smith" ],
    "sumOfAges": 72
  }
]

Допустим мы хотим получить только те пары, суммарное значение возраста в которых меньше 100, тогда нам нужно объявить переменную с помощью инструкции LET и выполнить постфильтрацию:

FOR user1 IN users
  FOR user2 IN users
    FILTER user1 != user2
    LET sumOfAges = user1.age + user2.age
    FILTER sumOfAges < 100
    RETURN {
        pair: [user1.name, user2.name],
        sumOfAges: sumOfAges
    }

В завершении давайте удалим один из созданных:

REMOVE "9883" IN users

Более того мы можем удалять документы в цикле, например так:

FOR user IN users
    FILTER user.age >= 30
    REMOVE user IN users

Эта конструкция удалит всех пользователей, которым более 30 лет. Для более детального знакомства с AQL воспользуйтесь официальным руководством.

Тэги: arangodb nosql базы данных


 


 
архив

подписка