Учебники

ArangoDB — Примеры запросов AQL

В этой главе мы рассмотрим несколько примеров запросов AQL к базе данных актеров и фильмов . Эти запросы основаны на графиках.

проблема

Имея коллекцию актеров, коллекцию фильмов и коллекцию ребер actIn (со свойством year) для соединения вершины, как показано ниже —

[Актер] <- сниматься в -> [Фильм]

Как мы получаем —

  • Все актеры, которые действовали в «movie1» ИЛИ «movie2»?
  • Все актеры, которые снимались в фильмах «кино1» и «кино2»?
  • Все общие фильмы между «актер1» и «актер2»?
  • Все актеры, которые снимались в 3 и более фильмах?
  • Во всех фильмах, где снимались ровно 6 актеров?
  • Количество актеров по фильмам?
  • Количество фильмов по актеру?
  • Количество фильмов, сыгранных актером в период с 2005 по 2010 год?

Решение

В процессе решения и получения ответов на вышеупомянутые запросы мы будем использовать Arangosh для создания набора данных и выполнения запросов по нему. Все запросы AQL являются строками и могут быть просто скопированы в ваш любимый драйвер вместо Arangosh.

Давайте начнем с создания набора тестовых данных в Арангоше. Сначала скачайте этот файл

# wget -O dataset.js
https://drive.google.com/file/d/0B4WLtBDZu_QWMWZYZ3pYMEdqajA/view?usp=sharing

Выход

...
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘dataset.js’
dataset.js [ <=> ] 115.14K --.-KB/s in 0.01s
2017-09-17 14:19:12 (11.1 MB/s) - ‘dataset.js’ saved [117907]

В выводе выше вы можете видеть, что мы загрузили файл JavaScript dataset.js. Этот файл содержит команды Arangosh для создания набора данных в базе данных. Вместо того, чтобы копировать и вставлять команды одну за другой, мы будем использовать опцию —javascript.execute на Arangosh, чтобы выполнять несколько команд неинтерактивно. Считайте, что это команда спасателей жизни!

Теперь выполните следующую команду на оболочке —

$ arangosh --javascript.execute dataset.js

Команда На Оболочке

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

Первый вопрос

Давайте возьмем первый вопрос: все актеры, которые действовали в «movie1» ИЛИ «movie2» . Предположим, мы хотим найти имена всех актеров, которые действовали в «TheMatrix» ИЛИ «TheDevilsAdvocate» —

Мы начнем с одного фильма за раз, чтобы получить имена актеров —

127.0.0.1:8529@_system> db._query("FOR x IN ANY 'movies/TheMatrix' actsIn
OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN x._id").toArray();

Выход

Мы получим следующий вывод —

[
   "actors/Hugo",
   "actors/Emil",
   "actors/Carrie",
   "actors/Keanu",
   "actors/Laurence"
]

Первый вопрос

Теперь мы продолжаем формировать UNION_DISTINCT из двух запросов NEIGHBORS, которые будут решением —

127.0.0.1:8529@_system> db._query("FOR x IN UNION_DISTINCT ((FOR y IN ANY
'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN
y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true,
uniqueVertices: 'global'} RETURN y._id)) RETURN x").toArray();

Выход

[
   "actors/Charlize",
   "actors/Al",
   "actors/Laurence",
   "actors/Keanu",
   "actors/Carrie",
   "actors/Emil",
   "actors/Hugo"
]

Первый вопрос 2

Второй вопрос

Давайте теперь рассмотрим второй вопрос: все актеры, которые участвовали как в «movie1», так и в «movie2» . Это почти идентично вопросу выше. Но на этот раз нас интересует не СОЮЗ, а ПЕРЕКЛЮЧЕНИЕ —

127.0.0.1:8529@_system> db._query("FOR x IN INTERSECTION ((FOR y IN ANY
'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN
y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true,
uniqueVertices: 'global'} RETURN y._id)) RETURN x").toArray();

Выход

Мы получим следующий вывод —

[
   "actors/Keanu"
]

Второй вопрос

Третий вопрос

Давайте теперь рассмотрим третий вопрос: все обычные фильмы между «actor1» и «actor2» . Это фактически идентично вопросу об общих актерах в movie1 и movie2. Нам просто нужно изменить начальные вершины. В качестве примера, давайте найдем все фильмы, где Хьюго Уивинг («Хьюго») и Киану Ривз снимаются вместе —

127.0.0.1:8529@_system> db._query(
   "FOR x IN INTERSECTION (
      (
         FOR y IN ANY 'actors/Hugo' actsIn OPTIONS 
         {bfs: true, uniqueVertices: 'global'}
          RETURN y._id
      ),
      
      (
         FOR y IN ANY 'actors/Keanu' actsIn OPTIONS 
         {bfs: true, uniqueVertices:'global'} RETURN y._id
      )
   ) 
   RETURN x").toArray();

Выход

Мы получим следующий вывод —

[
   "movies/TheMatrixReloaded",
   "movies/TheMatrixRevolutions",
   "movies/TheMatrix"
]

Третий вопрос

Четвертый вопрос

Давайте теперь рассмотрим четвертый вопрос. Все актеры, которые снялись в 3 и более фильмах . Этот вопрос другой; мы не можем использовать функцию соседей здесь. Вместо этого мы будем использовать краевой индекс и оператор COLLECT AQL для группировки. Основная идея состоит в том, чтобы сгруппировать все ребра по их startVertex (который в этом наборе данных всегда является актером). Затем мы удаляем всех актеров с менее чем 3 фильмами из результата, так как здесь мы включили количество фильмов, в которых актер сыграл —

127.0.0.1:8529@_system> db._query("FOR x IN actsIn COLLECT actor = x._from WITH
COUNT INTO counter FILTER counter >= 3 RETURN {actor: actor, movies:
counter}"). toArray()

Выход

[
   {
      "actor" : "actors/Carrie",
      "movies" : 3
   },
   
   {
      "actor" : "actors/CubaG",
      "movies" : 4
   },

   {
      "actor" : "actors/Hugo",
      "movies" : 3
   },

   {
      "actor" : "actors/Keanu",
      "movies" : 4
   },

   {
      "actor" : "actors/Laurence",
      "movies" : 3
   },

   {
      "actor" : "actors/MegR",
      "movies" : 5
   },

   {
      "actor" : "actors/TomC",
      "movies" : 3
   },
   
   {
      "actor" : "actors/TomH",
      "movies" : 3
   }
]

Четвертый вопрос

По оставшимся вопросам мы обсудим формирование запроса и предоставим только запросы. Читатель должен выполнить запрос самостоятельно на терминале Arangosh.

Пятый вопрос

Давайте теперь рассмотрим пятый вопрос: все фильмы, в которых снялись ровно 6 актеров . Та же идея, что и в запросе ранее, но с фильтром равенства. Однако теперь нам нужен фильм вместо актера, поэтому мы возвращаем атрибут _to

db._query("FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER
counter == 6 RETURN movie").toArray()

Количество актеров по фильмам?

Мы помним в нашем наборе данных _to на краю соответствует фильму, поэтому мы считаем, как часто появляется один и тот же _to . Это количество актеров. Запрос почти идентичен запросам до, но без фильтра после COLLECT

db._query("FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN
{movie: movie, actors: counter}").toArray()

Шестой вопрос

Давайте теперь рассмотрим шестой вопрос: количество фильмов актера .

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