在本章中,我们将在 Actors and Movies 数据库上考虑一些AQL示例查询.这些查询基于图表.
问题
给定一组演员和一组电影,以及一个actIn边缘集合(一年如下所示连接顶点 :
[Actor]< - act in - > [电影]
我们如何得到 :
所有演员谁扮演"movie1"或"movie2"?
所有演员都扮演"movie1"和"movie2"?
之间的所有常见电影"actor1"和"actor2"?
所有演过三部或三部以上电影的演员?
所有电影中只有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 OKLength: unspecified [text/html]Saving to: ‘dataset.js’dataset.js [ <=> ] 115.14K --.-KB/s in 0.01s2017-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' actsInOPTIONS {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'} RETURNy._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"]
第二个问题
现在让我们考虑第二个问题:所有演员谁同时扮演"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'} RETURNy._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true,uniqueVertices: 'global'} RETURN y._id)) RETURN x").toArray();
输出
我们将收到以下输出 :
[ "actors/Keanu"]
Third Question
现在让我们考虑一下第三个问题:"actor1"和"actor2"之间的所有常见电影.这实际上与关于movie1和movie2中的常见actor的问题相同.我们只需要改变起始顶点.作为一个例子,让我们找到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"]
第四个问题
现在让我们考虑第四个问题. 所有演过三部或三部以上电影的演员.这个问题不同;我们不能在这里利用邻居功能.相反,我们将使用AQL的edge-index和COLLECT语句进行分组.基本思想是通过 startVertex (在此数据集中始终为actor)对所有边进行分组.然后我们从结果中移除少于3部电影的所有演员,因为我们已经包括了演员演出的电影数量 :
127.0.0.1:8529@_system> db._query("FOR x IN actsIn COLLECT actor = x._from WITHCOUNT 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 FILTERcounter == 6 RETURN movie").toArray()
电影演员的数量?
我们记得在我们的数据集 _to 边缘对应电影,所以我们算一下
经常如何出现相同的 _to .这是演员的数量.该查询几乎与以前的
相同,但没有FILTER后的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 counterRETURN {actor: actor, movies: counter}").toArray()