Arangodb 简明教程

ArangoDB - AQL Example Queries

在本章中,我们将思考一个 @ {s0} 数据库上的几个 AQL 示例查询。这些查询都基于图表。

Problem

给定一组演员和一组电影,以及一个 actIn 边缘集合(带有一个 year 属性)以按照如下所示的方式连接顶点 −

@ {s1}

我们如何获得 −

  1. 在“movie1”或“movie2”中演出的所有演员?

  2. 在“movie1”和“movie2”中都演出的所有演员?

  3. “actor1”和“actor2”之间的所有公共电影?

  4. 在 3 部或更多电影中演出的所有演员?

  5. 正好 6 位演员出演的所有电影?

  6. 根据电影的演员数量?

  7. 根据演员的电影数量?

  8. 在 2005 年到 2010 年之间演员出演的电影数量?

Solution

在解决上述查询并获取答案的过程中,我们将使用 Arangosh 创建数据集并在其上运行查询。所有 AQL 查询都是字符串,可以轻松复制到您的首选驱动程序中,而不是 Arangosh。

我们首先在 Arangosh 中创建一个测试数据集。首先,下载 @ {s2} −

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

Output

...
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 文件 @ {s3}。该文件包含用于在数据库中创建数据集的 Arangosh 命令。我们不会逐个复制和粘贴这些命令,而是使用 Arangosh 上的 @ {s4} 选项来非交互式地执行多个命令。这简直是救命命令!

现在在 shell 上执行以下命令 −

$ arangosh --javascript.execute dataset.js
command on the shell

当提示时提供密码,如您在上述屏幕截图中看到的。现在我们已经保存了数据,因此我们将构建 AQL 查询来回答本章开头提出的具体问题。

First Question

我们来看第一个问题:@ {s5}。假设,我们想要找到在“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();

Output

我们将接收以下输出 −

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

现在,我们继续形成两个 NEIGHBORS 查询的 UNION_DISTINCT,这将是解决方案 −

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();

Output

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

Second Question

现在,我们考虑第二个问题: All actors who acted in both "movie1" AND "movie2" 。这几乎与上述问题完全相同。但这次,我们不感兴趣于 UNION,而感兴趣于 INTERSECTION −

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();

Output

我们将接收以下输出 −

[
   "actors/Keanu"
]
second question

Third Question

现在,我们考虑第三个问题: All common movies between "actor1" and "actor2" 。这实际上与电影 1 和电影 2 中的共同演员问题完全相同。我们只需要更改起始顶点即可。例如,让我们找出让休·杰克曼(Hugo)和基努·里维斯共同主演的所有电影 −

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();

Output

我们将接收以下输出 −

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

Fourth Question

现在,我们考虑第四个问题。 All actors who acted in 3 or more movies 。这个问题有所不同;我们不能在此处使用邻居函数。相反,我们将利用 AQL 的边缘索引和 COLLECT 语句进行分组。基本思想是按 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()

Output

[
   {
      "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
   }
]
fourth question

对于剩余的问题,我们将讨论查询形成,并仅提供查询。读者应在 Arangosh 终端上自行运行查询。

Fifth Question

现在,我们考虑第五个问题: All movies where exactly 6 actors acted in 。思路与之前的查询相同,但使用等式筛选器。然而,现在我们需要电影而不是演员,所以我们返回 _to attribute

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

根据电影的演员数量?

我们记得在我们的数据集 _to 中,边缘对应于电影,所以我们统计 _to 出现的次数。这是演员数量。该查询几乎与之前的查询相同,但 without the FILTER after COLLECT

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

Sixth Question

现在,我们考虑第六个问题: The number of movies by an actor

我们找到上述查询解决方法的方式也将帮助您找到此查询的解决方案。

db._query("FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter
RETURN {actor: actor, movies: counter}").toArray()