📜  ArangoDB-AQL示例查询

📅  最后修改于: 2020-11-28 13:14:28             🧑  作者: Mango


在本章中,我们将考虑演员和电影数据库上的一些AQL示例查询。这些查询基于图。

问题

给定一个演员集合和一个电影集合,以及一个actIn edge集合(具有year属性),以如下所示连接顶点-

[演员] <-表演-> [电影]

我们如何获得-

  • 所有在“ movie1”或“ movie2”中扮演过的演员?
  • 所有在“ movie1”和“ movie2”中都扮演过的演员?
  • “ actor1”和“ actor2”之间的所有常见电影?
  • 所有参演过3部或以上电影的演员?
  • 恰好有6位演员出演的所有电影?
  • 电影中有多少演员?
  • 演员的电影数量?
  • 在2005年至2010年间,由演员表演的电影数量是多少?

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

让我们首先在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命令,用于在数据库中创建数据集。与其一一复制和粘贴命令,不如使用Arangosh上的–javascript.execute选项以非交互方式执行多个命令。考虑一下救生命令!

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

$ 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"
]

第一个问题

现在我们继续形成两个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();

输出

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

第一个问题2

第二个问题

现在让我们考虑第二个问题:所有在“ movie1”和“ 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();

输出

我们将收到以下输出-

[
   "actors/Keanu"
]

第二个问题

第三题

现在让我们考虑第三个问题: “ actor1”和“ actor2”之间的所有常见电影。这实际上与关于movie1和movie2中的普通演员的问题相同。我们只需要更改起始顶点即可。举例来说,让我们找到所有由Hugo Weaving(“ Hugo”)和Keanu Reeves共同主演的电影-

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部以上电影的所有演员。这个问题是不同的。我们不能在这里利用邻居函数。相反,我们将使用edge-index和AQL的COLLECT语句进行分组。基本思想是根据所有边的startVertex (在此数据集中始终是actor)对其进行分组。然后,我们从结果中删除所有少于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之后没有FILTER-

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

第六题

现在让我们考虑第六个问题:演员的电影数量

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

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