Cypher入门教程

操作一个很简单的图

//创建你自己
CREATE (you:Person {name:"You"})
RETURN you
//你喜欢Neo4j数据库
MATCH  (you:Person {name:"You"})
CREATE (you)-[like:LIKE]->(neo:Database {name:"Neo4j" })
RETURN you,like,neo
//创建你的朋友们
MATCH (you:Person {name:"You"})
FOREACH (name in ["Johan","Rajesh","Anna","Julia","Andrew"] |
  CREATE (you)-[:FRIEND]->(:Person {name:name}))
//查找你的朋友
MATCH (you {name:"You"})-[:FRIEND]->(yourFriends)
RETURN you, yourFriends
//增加一个深度 创建一个neo4j专家Amanda,他是你朋友Anna的朋友哦
MATCH (neo:Database {name:"Neo4j"})
MATCH (anna:Person {name:"Anna"})
CREATE (anna)-[:FRIEND]->(:Person:Expert {name:"Amanda"})-[:WORKED_WITH]->(neo)
//查找到名词是Neo4j的Database,使用Neo4j工作的专家,以及你和专家的最短路径
MATCH (you {name:"You"})
MATCH (expert)-[:WORKED_WITH]->(db:Database {name:"Neo4j"})
MATCH path = shortestPath( (you)-[:FRIEND*..5]-(expert) )
RETURN db,expert,path

更多操作

首先创建一下这个演员-电影关系图:

// 这个不全的 最好执行neo4j示例的代码创建
LOAD CSV WITH HEADERS FROM "https://neo4j-contrib.github.io/developer-resources/cypher/movies_actors.csv" AS line
WITH line
WHERE line.job = "ACTED_IN"
MERGE (m:Movie {title:line.title}) ON CREATE SET m.released = toInt(line.released), m.tagline = line.tagline
MERGE (p:Person {name:line.name}) ON CREATE SET p.born = toInt(line.born)
MERGE (p)-[:ACTED_IN {roles:split(line.roles,";")}]->(m)
RETURN count(*);
//创建一个节点
CREATE (me:Person {name:"My Name"})
//返回所有的节点
MATCH (n)
RETURN n
//删除某节点和与其有关的所有关系
MATCH (me:Person {name:"My Name"})
OPTIONAL MATCH (me)-[r]-()
DELETE me,r
//排序 比如要找最老的那个人
MATCH (person:Person)
RETURN person.name, person.born
ORDER BY person.born
//跳过和限制  可以用于分页 减少查询的结果
MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie)
RETURN actor.name AS Actor, movie.title AS Movie
SKIP 10 LIMIT 10
//使用Distinct  因为同一个演员可能演过很多不同电影,返回的演员会有重复,增加Distinct去重
MATCH (actor:Person)-[:ACTED_IN]->()
RETURN DISTINCT actor
ORDER BY actor.born
LIMIT 5
//使用where
MATCH (person:Person)
WHERE person.name = "Tom Hanks"
RETURN person
//效果和下面这个一样
MATCH (person:Person {name:"Tom Hanks"})
RETURN person
//使用比较过滤 如查询和Tom Hanks一起演过电影并且年龄比他小的演员
MATCH (tom:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(actor:Person)
WHERE tom.name="Tom Hanks"
AND actor.born < tom.born
RETURN actor.name AS Name
// 查找和Tom Hanks一起演过电影并且年龄比他小的演员,以及比他小几岁,并且去除重复记录
MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(movie:Movie),
(movie)<-[:ACTED_IN]-(actor:Person) // note how the line break doesn't break the query
WHERE actor.born < tom.born
RETURN DISTINCT actor.name AS Name, (tom.born - actor.born) AS diff
//增加一个关系
match (ce:Person{name:"Clint Eastwood"}),(un:Movie{title:"Unforgiven"}) 
create (ce)-[:DIRECTED]->(un)
//查找和Gene Hackman一起合作过的演员
MATCH (gene:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(other:Person)
WHERE gene.name="Gene Hackman"
RETURN DISTINCT other
//找到一起合作过的演员兼导演
MATCH (gene:Person)-[:ACTED_IN]->()<-[:ACTED_IN]-(other:Person)
WHERE gene.name="Gene Hackman"
AND exists( (other)-[:DIRECTED]->() )  //加个not就把导演过滤掉
RETURN DISTINCT other

小练习

1.找到所有的Tom Hanks出演的电影

match (tom:Person{name:'Tom Hanks'})-[:ACTED_IN]->(movie) return tom,movie

2.找到所有Tom Hanks 2000年以后演的电影

match (tom:Person{name:'Tom Hanks'})-[:ACTED_IN]->(movie) 
where movie.released > 2000 
return tom,movie
//或者这样 都写到where条件里
MATCH (tom:Person)-[:ACTED_IN]->(movie)
WHERE tom.name="Tom Hanks"
AND movie.released > 2000
RETURN tom,movie

3.查找Keanu Reeves扮演角色Neo的所有电影

match (keanu :Person{name:'Keanu Reeves'})-[r:ACTED_IN]->(movie)
where 'Neo' in r.roles 
return keanu,movie
//或者这样写
MATCH (keanu:Person)-[r:ACTED_IN]->(movie)
WHERE keanu.name="Keanu Reeves"
AND "Neo" IN r.roles
RETURN movie.title

路径匹配

(movie)<-[:DIRECTED]-(director)
//也可以反过来写
(director)-[:DIRECTED]->(movie)
//可变长路径
MATCH (node1)-[*]-(node2)
//遍历任意长度的关系
(a)-[*]->(b)
//查找depth深度的关系
(a)-[*depth]->(b)
//1-4级深度的关系
(a)-[*1..4]->(b)
//3级深度的KNOWS关系
(a)-[:KNOWS*3]->(b)
//KNOWS关系或2级深度的LIKES关系
(a)-[:KNOWS|:LIKES*2..]->(b)

路径命名作为Return返回值

MATCH p=(actor:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN p

MATCH p=(actor:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN nodes(p)

MATCH p=(actor:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN rels(p)

MATCH p1=(actor:Person)-[:ACTED_IN]->(movie:Movie), p2=(director:Person)-[:DIRECTED]->(movie)
RETURN p1, p2

索引和标签

与其他数据库不同,Neo4j不使用索引来加快JOIN操作。但是,它们对于通过值,文本前缀或范围找到起点很有用。您将创建一个标签特定索引,因为索引绑定到具体的标签属性组合。

因此,如果您希望Movies能够基于title更高效的搜索,则可以运行以下Cypher命令:

CREATE INDEX ON :Movie(title)
//删除索引
DROP INDEX ON :Movie(title)

聚合

//count(x)  查找每个演员演的电影的数量
match(p:Person)-[:ACTED_IN]->(movie:Movie)
return p.name,count(movie) as num
order by num desc
//collect(x)  返回每个演员拍过的电影集合
MATCH (person:Person)-[:ACTED_IN]->(movie:Movie)
RETURN person.name, collect(movie.title)
// 返回每个演员合作过导演的集合
MATCH (person:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN person.name, collect(director.name)
// 如果演员和导演合作过多次 那个导演会出现多次 去重的话这样写
MATCH (person:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person)
RETURN person.name, collect(DISTINCT director.name) as directors
// 查找最忙的5个演员
MATCH (actor:Person)-[:ACTED_IN]->(movie)
RETURN actor.name, count(movie)
ORDER BY count(movie) DESC
LIMIT 5

推荐引擎

// 写一个牛逼一点的关系
MATCH (keanu:Person {name:"Keanu Reeves"})-[:ACTED_IN]->()<-[:ACTED_IN]-(coworker:Person),
      (coworker)-[:ACTED_IN]->()<-[:ACTED_IN]-(coworkerOfCoworker)
WHERE coworkerOfCoworker <> keanu  AND NOT((keanu)-[:ACTED_IN]->()<-[:ACTED_IN]-(coworkerOfCoworker))
RETURN coworkerOfCoworker.name, count(coworkerOfCoworker)
ORDER BY count(coworkerOfCoworker) DESC
LIMIT 3

导入数据

Cypher提供了一种优雅的内置方法将表格CSV数据导入图形结构。

ex:将一个下面这样的movies.csv导入图,实际上就是按行读取,将内容塞进创建语句的循环

ID,标题,国家,一年
1,美国华尔街1987年
2,美国总统,美国,1995年
3,肖申克救赎,美国,1994年
LOAD CSV WITH HEADERS
FROM "http://neo4j.com/docs/stable/csv/intro/movies.csv"
AS line
CREATE (movie:Movie { id:line.id, title:line.title, released:toInt(line.year) })

persons.csv

ID,名称
1,查理恩
2,奥利佛石
3,迈克尔·道格拉斯
4,Martin Sheen
5,摩根·弗里曼
LOAD CSV WITH HEADERS
FROM "http://neo4j.com/docs/stable/csv/intro/persons.csv"
AS line
MERGE (actor:Person { id:line.id })
ON CREATE SET actor.name=line.name;

roles.csv

PERSONID,movieId,角色
1,1,Bud Fox
4,1,卡尔·福克斯
3,1,Gordon Gekko
4,2,AJ MacInerney
3,2,安德鲁·谢弗德总统
5,3,Ellis Boyd'Red'Redding
LOAD CSV WITH HEADERS
FROM "http://neo4j.com/docs/stable/csv/intro/roles.csv"
AS line
MATCH (movie:Movie { id:line.movieId })
MATCH (person:Person { id:line.personId })
CREATE (person)-[:ACTED_IN { roles: [line.role]}]->(movie);

导入非正规化数据

movie_actor_roles.csv

称号;释放;演员;负担;字符
回到未来; 1985; Michael J. Fox; 1961; Marty McFly
回到未来; 1985;克里斯托弗·劳埃德; 1938年;博士。Emmet Brown
LOAD CSV WITH HEADERS
FROM "http://neo4j.com/docs/stable/csv/intro/movie_actor_roles.csv"
AS line FIELDTERMINATOR ";"
MERGE (movie:Movie { title:line.title })
ON CREATE SET movie.released = toInt(line.released)
MERGE (actor:Person { name:line.actor })
ON CREATE SET actor.born = toInt(line.born)
MERGE (actor)-[r:ACTED_IN]->(movie)
ON CREATE SET r.roles = split(line.characters,",")

导入大型数据集

如果您导入更大量的数据(超过10000行),建议在您的LOAD CSV子句前面加一个PERIODIC COMMIT提示。这允许数据库定期提交导入事务,以避免大型事务状态的内存流失。

更多内容请参考 官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容