手机版 欢迎访问it开发者社区(www.mfbz.cn)网站

当前位置: > 开发

Neo4j cypher语言查询练习

时间:2021/4/2 5:28:03|来源:|点击: 次

Neo4j是一种图数据库,在查询时用到的语言也跟SQL不一样,下面就是一些我遇到的一些比较好的例题,我会分享我的代码和解答方式。
这些问题都是基于imdb电影数据集,并且每道题都有很多种查询思路,因此也有很多种查询代码,我只分享我的思路。

注:我的数据库关系图:
在这里插入图片描述
1. 构建数据库中所有文件的关系图:
解答:分两段进行,第一段先用create()函数来创建实体与实体件的联系,然后第二段用match()来运行。

create (a:imdb {name:“Movies”})
create (b:imdb {name:“Actors”})
create (c:imdb {name:“Directors”})
create (d:imdb {name:“Writers”})
create (e:imdb {name:“MoviesToActors”})
create (f:imdb {name:“MoviesToDirectors”})
create (g:imdb {name:“MoviesToWriters”})
create (h:imdb {name:“RunningTimes”})
create (i:imdb {name:“Rating”})
create (b)-[:Acted_In]->(e)
create ©-[:Directed]->(f)
create (d)-[:Wrote]->(g)
create (a)-[:Have]->(e)
create (a)-[:Have]->(f)
create (a)-[:Have]->(g)
create (a)-[:Run_In]->(h)
create (a)-[:Rated_In]->(i)

MATCH (N:imdb) RETURN N
在这里插入图片描述

2. 罗恩·霍华德(Ron Howard)执导了多少部电影?
解答:本题比较简单,只需在match电影与导演后,输入导演的名字即可。

MATCH(M:Movie)-[DIRECTED_BY]->(D:Director)
WHERE D.name CONTAINS ‘Howard, Ron’
RETURN count(DISTINCT M)as Ron_Howard_Films

在这里插入图片描述
3. 查询数据集中女性演员的人数和男性演员的人数。
解答:我们可以设两个类:maleNum和femaleNum,再用count()函数来将人数统计并放入这两个类中。为了防止混淆,我们需要使用AS功能,即:count(male) AS maleNum
代码:
MATCH(male:Actor{sex:“M”}) WITH COUNT(male) as malenumber
MATCH(female:Actor{sex:“F”}) WITH COUNT(female) as femalenumber
RETURN malenumber, femalenumber

在这里插入图片描述4. 查询数据库中最老的电影的年份。
解答:对于这道题,我的想法是将电影按照电影的出品年份来进行排序,然后只显示第一个就好了。

MATCH(n:Movie)
RETURN n.movieID,n.title,n.year ORDER BY n.year LIMIT 1

在这里插入图片描述
5. 查询超过5名导演执导的电影的电影标题和导演人数。
解答:先用count()函数查找超过五名导演执导的电影,再列出电影名和导演人数。

MATCH(M:Movie)-[:DIRECTED_BY]->(D:Director) WITH M, COUNT(DISTINCT D.directorID) AS DIRECTOR_COUNT
WHERE DIRECTOR_COUNT > 5
RETURN M.title as TITLE_OF_MOVIE,DIRECTOR_COUNT

在这里插入图片描述
6. 查询播放时间在15分钟至20分钟之间的电影数量(包含)
解答:本题仅需在match之后添加where语句来进行范围设置,即可开始查询。

MATCH(M:Movie)-[:RUNS_FOR]->(R:Runningtime)
WHERE R.time1 >= 15 and R.time1 <= 20
RETURN COUNT (DISTINCT M.movieID) AS MOVIES_BETWEEN_15_TO_20

在这里插入图片描述
7. 查询两个演员Bill Nighy和Ewan McGregor都参演的电影的电影名称。
解答:**方法一:**本题需要在Movie的两侧同时进行match才能保证查询到的电影中同时含有"Bill Nighy"和"Ewan McGregor"两个名字

MATCH (a1:Actor)-[:ACTED_IN]->(n:Movie)<-[:ACTED_IN]-(a2:Actor)
WHERE a1.name CONTAINS ‘Nighy, Bill’ and a2.name CONTAINS ‘McGregor, Ewan’
RETURN DISTINCT n.title

**方法二:**如图,进行两次match:
在这里插入图片描述
8. 查询多少部电影中男演员比女演员少?
解答:这道题我用的方法比较笨,通过两次match统计出每部电影中男演员和女演员的数量,再通过比较,如果符合标准再通过count()函数来计数

MATCH(m:Movie)-[:HAS_ACTOR]->(a1:Actor{sex:“M”}) WITH m, COUNT(a1) AS MALE_COUNT
MATCH(m:Movie)-[:HAS_ACTOR]->(a2:Actor{sex:“F”}) WITH m, MALE_COUNT, COUNT(a2) AS FEMALE_COUNT
WHERE FEMALE_COUNT > MALE_COUNT
RETURN COUNT(m)

在这里插入图片描述
9. 查找一起合作过超过10部电影的演员,包括他们的名字和他们共同出演的电影数量。
解答:本题较难!本题需要运用三种不同的函数,分别是id(), collect()和size()函数。
先用id()函数记录下两个演员的信息,然后再将他们跟电影信息一起收录到一个子数据库中并开始计数,如果满足要求(即大于10部电影),则输出结果。

MATCH(a1:Actor)<-[:HAS_ACTOR]-(m:Movie)-[:HAS_ACTOR]->(a2:Actor)
WHERE id(a1)<id(a2) WITH a1, a2, collect(m) AS CommonMovies
WHERE size(CommonMovies)>10
RETURN a1.name AS FRIST_NAME, a2.name AS SECOND_NAME, size(CommonMovies) AS COMMON_MOVIES

在这里插入图片描述
10. 查询数据集中每十年发行的电影数量,如下所示:(1970-79、1980-89、1990-99、2000-2009、2010-2019)。
解答:本题仅需在sum()函数中设立边界值,并在规定区间内进行查询即可。

MATCH (M:Movie)
RETURN SUM(CASE WHEN 1970 <= M.year <=1979 THEN 1 ELSE 0 END) AS 70s,
SUM(CASE WHEN 1980 <= M.year <=1989 THEN 1 ELSE 0 END) AS 80s,
SUM(CASE WHEN 1990 <= M.year <=1999 THEN 1 ELSE 0 END) AS 90s,
SUM(CASE WHEN 2000 <= M.year <=2009 THEN 1 ELSE 0 END) AS 00s,
SUM(CASE WHEN 2010 <= M.year <=2019 THEN 1 ELSE 0 END) AS 10s

在这里插入图片描述
11. 汤姆·汉克斯(Tom Hanks)在1993年演出了几部电影?
解答:本题仅需要在match了movie跟actor之后规定演员名字和电影的year即可。

MATCH(M:Movie)-[:HAS_ACTOR]->(A:Actor)
WHERE A.name CONTAINS “Hanks, Tom” AND M.year=1993
RETURN COUNT(DISTINCT M) AS MOVIE_OF_TOM_IN_1993

在这里插入图片描述
12. 根据每种电影类型的平均排名,查询获得15,000或更多选票的得分最高的前4种类型的电影。
解答:本题光看名字就十分绕脑,所以我们需要先理清题目的要求再开始做题。首先我们需要找出选票大于15000的电影。然后为了获得电影的种类,我需要将movie和director相match来获得genre属性(我的数据集中的movie文件中没有genre属性,只有director文件中有,如果你们的movie文件中genre属性,则可跳过这一步)
随后我们需要通过AVG()函数来获得电影类型的平均排名,再进行排序并输出。

MATCH(M:Movie)-[:IS_RATED]->(R:Rating)
WHERE R.votes > 15000
MATCH(M:Movie)-[G:DIRECTED_BY]->(D:Director)
RETURN G.Genre AS MOVIE_GENRE, AVG(R.rank) AS AVERAGE_RANK
ORDER BY AVERAGE_RANK
DESC LIMIT 4

在这里插入图片描述
13. 查询曾出演过9种及以上不同类型电影的所有演员。
解答:像我之前说过的那样,因为我数据集的问题,所以我不得不将movie再次跟director进行match,如果你们的数据集不一样,可酌情免去此步骤。在我将演员与电影类型进行链接之后,通过带有distinct(避免重复计算电影类型)的count()函数来统计电影类型数。在统计完后,如果符合题目要求,则输出运行结果。

MATCH(A:Actor)-[:ACTED_IN]->(M:Movie)-[G:DIRECTED_BY]->(D:Director) WITH A.name AS ACTOR_NAME, COUNT(DISTINCT G.Genre) AS NUM_OF_GENRES
WHERE NUM_OF_GENRES >= 9
RETURN ACTOR_NAME, NUM_OF_GENRES

在这里插入图片描述
14. 查询有多少部电影中有一位女演员曾执导并编写过这部电影?
解答:本题有点难度。首先我们要将Actor与Director进行match,然后再将Actor与Writer进行match并进行比较,如果Actor, Director和Writer的名字一致,则放入count()函数中进行计数(用Actor, Director或Writer的任意一个进行计数即可)

MATCH (a:Actor{sex:“F”})-[:ACTED_IN]->(m:Movie)-[:DIRECTED_BY]->(D:Director)
MATCH (a:Actor{sex:“F”})-[:ACTED_IN]->(m:Movie)-[:WROTE_BY]->(W:Writer)
WHERE a.name = D.name and a.name = W.name
RETURN count(a)

在这里插入图片描述
15. 查询有多少部电影是演员自己编写并导演,但是他们自己并没有出演的?
解答:首先我们需要将director和writer进行match, 然后再单独match演员和电影(注意两次match中电影前的标注必须是不同的,我用了m与m1),随后开始筛选。当演员的名字与导演以及作者的名字一致,且电影序号m跟m1不一致时,开始用count()函数来统计结果。

MATCH (a:Actor)-[:ACTED_IN]->(m:Movie)
MATCH (D:Director)-[:DIRECTED]->(m1:Movie)-[:WROTE_BY]->(W:Writer)
WHERE D.name = W.name and D.name = a.name
AND NOT m1.movieID = m.movieID
RETURN count(DISTINCT m)
在这里插入图片描述

Copyright © 2002-2019 某某自媒体运营 版权所有