2.4 官方入门实例介绍
为了方便读者入门,Neo4j Web管理界面提供了一个官方入门实例“电影关系图”,帮助初学者在自己电脑上一步步创建一个入门级别的图数据结构。本节将围绕这个“电影关系图”实例一步步讲解、分析其创建和查询等操作。
首先,打开Neo4j Web管理界面(如图2-47所示)后,在引导实例区单击Write Code链接进入代码书写引导页,然后单击Movie Graph下的Create a graph链接就进入“电影关系图”实例引导界面了,如图2-48所示。
图2-47 Neo4j Web管理界面
图2-48 引导实例区
“电影关系图”实例将电影、电影导演、演员之间的复杂网状关系作为蓝本,使用Neo4j创建三者关系的图结构,虽然实例数据规模小但结构是相对完整的。
这个实例将指引读者学习以下入门操作:
(1)创建图数据:将电影、演员、导演等图数据导入到Neo4j数据库中。
(2)检索节点:检索特定电影和演员。
(3)查询关系:发现相关的演员和导演。
(4)查询关系路径:查询他们之间的关系路径。
2.4.1 创建图数据
单击“电影关系图”实例引导页的右侧换页箭头可以看到一些实例代码,其中包含多个带有CREATE关键字的Cypher语句。单击代码块,代码块将自动填入到命令行输入区。单击运行命令按钮,图数据就创建完成了。
下面,对这些创建语句进行分析说明,先不必完全弄懂这些命令,只需要了解它们的目的即可,关于这些Cypher语句的具体学习,在后续章节会有详细介绍。
【程序2-1】创建电影节点
CREATE (TheMatrix:Movie {title:'The Matrix',
released:1999, tagline:'Welcome to the Real World'})
上面的Cypher语句使用CREATE指令创建了一个Movie节点,这个节点上带有三个属性{title:'The Matrix', released:1999, tagline:'Welcome to the Real World'},分别表示这个电影的标题:The Matrix、发布时间:1999、宣传词:Welcome to the Real World。
上述Cypher语句运行后将会在数据库中创建一个Movie节点,在数据库中的存储形态如图2-49所示。
图2-49 Movie节点
【程序2-2】创建人物节点
CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})
上面代码使用CREATE指令创建了一个Person节点,节点带有两个属性{name:'Keanu Reeves', born:1964}。
在后续的6行代码中都使用了同样的CREATE指令分别创建了人物:Carrie、Laurence、Hugo、LillyW、LanaW和JoelS。
【程序2-3】创建演员、导演关系
CREATE (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix), (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrix), (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrix), (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrix), (LillyW)-[:DIRECTED]->(TheMatrix), (LanaW)-[:DIRECTED]->(TheMatrix), (JoelS)-[:PRODUCED]->(TheMatrix)
上面代码中除了使用CREATE指令外,还使用了箭头运算符,如:(Keanu)-[:ACTED_IN{roles:['Neo']}]->(TheMatrix),这一行的意思是创建一个演员参演电影的关系,演员Keanu以角色roles:['Neo']参演ACTED_IN到电影TheMatrix中。代码前4行都是创建演员参演电影关系的指令。
第5行指令:(LillyW)-[:DIRECTED]->(TheMatrix),意思是创建导演与电影的关系,即LillyW导演了“[:DIRECTED]”电影TheMatrix。
上面的指令运行完后,数据库中会有以下存储形态,如图2-50所示。
图2-50 导演、电影关系图
这样数据库中一个电影、演员、导演、制片商的关系就创建出来了。在后面的代码中用了同样的指令分别创建了电影:The Matrix Revolutions、The Devil's Advocate、A Few Good Men、Top Gun、Jerry Maguire等,然后又创建了与这些电影相关的演员、导演、制片商与他们之间的关系。
通过上述的创建指令就把“电影关系图”实例创建完成了。
2.4.2 检索节点
图数据结构创建完毕后,下面介绍检索节点的相关操作。
2.4.2.1 查找人员
【程序2-4】查找名为“Tom Hanks”的人物
MATCH (tom {name: "Tom Hanks"}) RETURN tom
上面语句使用MATCH指令查找匹配条件:{name: "Tom Hanks"}的节点,执行的结果如图2-51所示。
图2-51 查找到的节点
可以在结果显示区看到查询到的节点,注意在结果展示区单击节点图标,会查看到节点的属性。
2.4.2.2 查找电影节点
【程序2-5】查找名为“Cloud Atlas”的电影
MATCH (cloudAtlas {title: "Cloud Atlas"}) RETURN cloudAtlas
上面指令查找匹配条件{title: "Cloud Atlas"}的节点,返回结果如图2-52所示。
图2-52 查找到的节点
2.4.2.3 随机查找多个人物的人名
【程序2-6】随机查找10个人物的人名
MATCH (people:Person) RETURN people.name LIMIT 10
上面指令查找10个Person节点,然后返回每个节点的name属性,返回结果如图2-53所示。
图2-53 name属性列表
在本次结果中,由于只返回name属性,所以就不用图形化的形式返回了。
2.4.2.4 查找多个电影
【程序2-7】查找1990年到2000年发行的电影的名称
MATCH (nineties:Movie) WHERE nineties.released > 1990 AND nineties.released < 2000 RETURN nineties.title
上面指令略微复杂,首先匹配Movie节点,然后使用WHERE子句查询电影的released属性值大于1990并且小于2000条件的节点,然后只返回匹配节点的title属性。返回结果为如图2-54所示。
图2-54 title属性列表
2.4.3 查询关系
下面拓展MATCH指令的使用。
2.4.3.1 查找演员参演的电影
【程序2-8】查找“Tom Hanks”参演过的电影的名称
MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(tomHanksMovies) RETURN tom, tomHanksMovies
上述指令首先匹配节点类型为Person、属性为{name: "Tom Hanks"}的节点,然后匹配此节点具有关系[:ACTED_IN],并且此关系指向某个电影节点的节点。返回结果如图2-55所示。
图2-55 “Tom Hanks”参演过的电影
通过结果可以看到演员Tom Hanks参演过的所有电影。
【程序2-9】查找谁导演了电影“Cloud Atlas”
MATCH (cloudAtlas {title: "Cloud Atlas"})<-[:DIRECTED]-(directors) RETURN directors.name
上面指令首先匹配属性为{title: "Cloud Atlas"}的节点,然后匹配此节点具有关系[:DIRECTED]并且是被某个节点指向的节点,再返回匹配节点的name属性。返回结果如图2-56所示。
图2-56 电影Cloud Atlas的导演名单
通过结果可以看到Lily Wachowski、Lana Wachowski、Tom Tykwer导演了电影Cloud Atlas。
【程序2-10】查找与Tom Hanks同出演过电影的人
MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]- (coActors) RETURN coActors.name
上面指令首先匹配节点类型为Person、属性为{name:"Tom Hanks"}的节点,然后匹配此节点通过[:ACTED_IN]关系指向的节点m,并且同时匹配某个节点coActors也通过[:ACTED_IN]关系指向的节点m,然后返回匹配节点m的name属性。返回结果如图2-57所示。
图2-57 与“Tom Hanks”同出演过电影的人
这样与Tom Hanks同时出演过电影的人的姓名就查出来了。
【程序2-11】查找与电影“Cloud Atlas”相关的所有人
MATCH (people:Person)-[relatedTo]-(:Movie {title: "Cloud Atlas"}) RETURN people.name, Type(relatedTo), relatedTo
上面指令首先匹配节点类型为Person的节点,然后匹配节点类型为Movie、节点属性为{title: "Cloud Atlas"}的节点,最后匹配他们两者之间存在某种关系(无论是导演还是演员关系)的情况,然后将人名、电影的关系类型、电影的关系同时返回。返回结果如图2-58所示。
图2-58 与电影“Cloud Atlas”相关的所有人
通过结果可以看到返回了三列数据,这与RETURN语句后面的people.name、Type(relatedTo)、 relatedTo相对应。
2.4.3.2 查询关系路径
您或许听说过“六度空间”理论,也就是说,世界上任何两个人,他们之间至多通过6条关系路径就可以相互联系到彼此。使用Neo4j的关系路径查询可以查找任意深度的关系路径,也就很轻松地能够实现人脉关系查询了。
【程序2-12】查找与演员“Kevin Bacon”存在4条及以内关系的任何演员和电影
MATCH (bacon:Person {name:"Kevin Bacon"})-[*1..4]-(hollywood) RETURN DISTINCT hollywood
上面指令首先匹配节点类型为Person、属性为{name: " Kevin Bacon "}的节点,然后将关系深度限制为从1到4再进行遍历,最后返回匹配的所有节点。返回结果如图2-59所示。
图2-59 与演员Kevin Bacon存在4条及以内关系的演员和电影
通过结果可以看到演员Kevin Bacon4度关系以内的演员和电影网络是很庞大的。
【程序2-13】查找与演员Kevin Bacon与Meg Ryan之间的最短关系路径
MATCH p=shortestPath( (bacon:Person {name:"Kevin Bacon"})-[*]-(meg:Person {name:"Meg Ryan"}) ) RETURN p
上面指令首先匹配节点类型为Person、属性为{name: "Kevin Bacon"}的节点,再匹配节点类型为Person、属性为{name: " Meg Ryan "}的节点,两者用[*]关系操作符相连代表两者存在任意深度的关系,然后使用shortestPath方法返回两者在所有深度关系遍历路径中最短的一条。返回结果如图2-60所示。
图2-60 “Kevin Bacon”与“Meg Ryan”之间的最短关系路径
通过结果可以看到演员Meg Ryan与Tom Hanks同参演过Joe Versus the Volcano电影,而Tom Hanks与Kevin Bacon同参演过Apollo 13电影,这就是他们两者之间的最短关系路径。
2.4.4 思考与练习
基于这个“电影关系图”实例,可以考虑一下其他的应用场景:要为Tom Hanks推荐新的合作伙伴,一个比较好的办法就是通过认识Tom Hanks的人的人脉来寻找新的合作伙伴。
对于Tom Hanks来说,这意味着:
第一步,先找到Tom Hanks还没有合作过的演员,但Tom Hanks的合作伙伴曾经与其合作过。
第二步,找到一个可以向他的潜在合作者介绍Tom Hanks的人。
【程序2-14】查找没有与Tom Hanks合作过的演员
MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]- (coActors), (coActors)-[:ACTED_IN]->(m2)<-[:ACTED_IN]-(cocoActors) WHERE NOT (tom)-[:ACTED_IN]->(m2) RETURN cocoActors.name AS Recommended, count(*) AS Strength ORDER BY Strength DESC
结果如图2-61所示。
图2-61 没有与Tom Hanks合作过的演员
【程序2-15】找人将Tom Hanks介绍给Tom Cruise
MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]- (coActors), (coActors)-[:ACTED_IN]->(m2)<-[:ACTED_IN]-(cruise:Person {name:"Tom Cruise"}) RETURN tom, m, coActors, m2, cruise
结果如图2-62所示。
图2-62 找人将Tom Hanks介绍给Tom Cruise
2.4.5 清空数据库
上面的数据在操作完后,有时候需要清理掉这些数据。下面的代码就可以做到。
【程序2-16】清空所有Person、Movie节点及其所有关系
MATCH (a:Person), (m:Movie) OPTIONAL MATCH (a)-[r1]-(), (m)-[r2]-() DELETE a, r1, m, r2
这样操作完成后,为了查询数据是否已经被清空了,可以运行以下命令先看数据库中是否还有任何数据。
【程序2-17】查询任意数据
MATCH (n) RETURN n
如果没有,就说明已经删除成功了。