图数据库

您所在的位置:网站首页 neo4j部署 图数据库

图数据库

#图数据库| 来源: 网络整理| 查看: 265

Neo4j使用详解 目录 目录Q / ANeo4j 安装Basic conceptCypher BasicMATCH 查询WITHINDEX 索引最短路径 Shortest path Movie Graph Create 创建Find 查找Query 查询Solve 最短路径 Bacon PathRecommend 推荐Clean up 删除电影数据LOAD CSV 加载 Persons Movies 数据 Northwind Graph Northwind 数据表结构加载 Product Catalog CSV 文件创建 Product Catalog 关系图加载 Customer Orders CSV 文件创建 Customer Orders 关系图Order Detail CSV 文件 Neo4j CQL 命令格式 Neo4j CQL 简介CREATEMATCHRETURNWHEREDELETEREMOVESETORDER BYUNIONASLIMITSKIPMERGENULL 值INID 属性INDEX 索引UNIQUE 约束DISTINCT Neo4J CQL 函数 String 字符串函数Aggregation 聚合函数Relationship 关系函数 Neo4j 图形算法 链接遍历和寻路算法Centrality Algorithms社区发现算法 APOC 存储过程库 介绍算法介绍 py2neo 链接Node Relation PropertyNode Relationship 的其他方法Subgraph 子图WalkableGraphRecordTableTransactionCursorErrors and WarningsMatchingOGMCypher Q / A Q: AuthError: The client is unauthorized due to authentication failurefrom py2neo import Graph g = Graph() AuthError: The client is unauthorized due to authentication failure. A: 默认使用的用户名 / 密码是 neo4j / password,需要匹配自己的用户名密码neo4j-client -u neo4j -p 123456 bolt://localhost:7687 g = Graph(auth=("neo4j", "123456")) 或通过 :server user add 添加新用户Q: TypeError: Parameters of type map are not supportedfrom py2neo import Graph, Node g = Graph("http://localhost:7474") a = Node('Person', name='Alice') g.create(a) TypeError: Parameters of type map are not supported A: http 初始化的 graph 不能 create,必须用 bolt graph create 过 [ ??? ]g2 = Graph("bolt://...", auth=(...)) g2.create(a) g.create(a) Neo4j 安装 neo4j githubNeo4j Graphs for EveryoneNeo4j Desktop Debian InstallationNeo4j Debian PackagesThe Neo4j Developer ManualNeo4j 中文社区Neo4j 中文手册Cypher 中文文档O’Reilly’s Graph DatabasesNeo4j and Apache Spark安装 Neo4j''' Neo4j 要求 JAVA 1.8 ''' apt install maven openjdk-8-jdk apt install debhelper devscripts dos2unix dpkg make xmlstarlet export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ''' 方法1,Github 中的安装方法,启动一个安装程序,需要更多配置 ''' # You will need a license for install4j, which is only needed for Neo4j Desktop curl -O http://download-keycdn.ej-technologies.com/install4j/install4j_linux_6_1_4.deb dpkg -i install4j_linux_6_1_4.deb ''' 方法2,debian source list,E: The repository 'https://debian.neo4j.org/repo stable/ Release' does not have a Release file. ''' wget -O - https://debian.neo4j.org/neotechnology.gpg.key | sudo apt-key add - echo 'deb https://debian.neo4j.org/repo stable/' | sudo tee -a /etc/apt/sources.list.d/neo4j.list sudo apt-get update ''' 方法3,tar 文件 ''' # https://neo4j.com/download/other-releases/#releases wget https://go.neo4j.com/download-thanks.html?edition=community&release=3.4.1&flavour=unix tar xvf neo4j-community-3.4.1-unix.tar.gz cd neo4j-community-3.4.1 cd bin ./neo4j console # INFO Remote interface available at http://localhost:7474/ # Add bin to envirenment PATH 启动neo4j start # Browse at http://localhost:7474/ Default username / password: neo4j / neo4j 初次登录会要求修改密码添加新用户:server user add Add a new user, and test with neo4j-client# Username: neo4j-user-1, password: 123456 neo4j-client -u neo4j-user-1 -p 123456 bolt://localhost:7687 Hello worldCREATE (matrix:Movie { title:"The Matrix", released:1997 }) CREATE (cloudAtlas:Movie { title:"Cloud Atlas", released:2012 }) CREATE (forrestGump:Movie { title:"Forrest Gump", released:1994 }) CREATE (keanu:Person { name:"Keanu Reeves", born:1964 }) CREATE (robert:Person { name:"Robert Zemeckis", born:1951 }) CREATE (tom:Person { name:"Tom Hanks", born:1956 }) CREATE (tom)-[:ACTED_IN { roles: ["Forrest"]}]->(forrestGump) CREATE (tom)-[:ACTED_IN { roles: ['Zachry']}]->(cloudAtlas) CREATE (robert)-[:DIRECTED]->(forrestGump) RETURN matrix,cloudAtlas,forrestGump,keanu,robert,tom [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XTlvWKAD-1678944724459)(images/neo4j_hello_world.jpg)] Basic concept

Graph 图 是表示对象与对象之间关系的方法

对象 又称 节点 Node / 顶点 Vertex / 实体 Entity,描述具体的一件事物关系 又称 边 edge,描述对象之间的关系G=(V, E) 表示一张图,V 表示节点的集合,E 表示边集合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0WkpHSMG-1678944724460)(images/neo4j_node_example.jpg)]

图的学习任务分类

社交网络 / 搜索排名 / 评分系统 / 推荐系统 / 知识图谱 / 风险控制节点上的任务:利用图中节点的关系可以做包括分类(比如风险识别、价值排名等任务)、聚类(社群检测、用户画像等任务)边上的任务:通过图中节点之间是否有边可以做比如推荐、知识推理等任务图上的任务:图可以做像高分子分类、3D视觉分类等任务

Graph 图 基本组成

Nodes 节点 数据的名称(a) // actors (m) // movies ( ) // some anonymous node Relationships 关系 节点之间的连接-[r]-> //a relationship referred to as "r" (a)-[r]->(m) //actors having a relationship referred to as "r" to movies -[:ACTED_IN]-> //the relationship type is ACTED_IN (a)-[:ACTED_IN]->(m) //actors that ACTED_IN some movie (d)-[:DIRECTED]->(m) //directors that DIRECTED some movie 关系有特定的方向与类型关系可以包含属性 Properties 属性 键值队的形式存储数据值(m {title:"The Matrix"}) //Movie with a title property (a {name:"Keanu Reeves",born:1964}) //Actor with name and born property (a)-[:ACTED_IN {roles:["Neo"]}]->(m) //Relationship ACTED_IN with roles property Label 标签 节点可以通过标签组合在一起(a:Person) //a Person (a:Person {name:"Keanu Reeves"}) //a Person with properties (a:Person)-[:ACTED_IN]->(m:Movie) //a Person that ACTED_IN some movie 一个节点可以有 0 个或多个标签标签没有属性

Editor

:help 查看命令的帮助信息:clear 清空:play 运行// Guides :play intro :play concepts :play cypher // Examples :play movie graph :play northwind graph shift-enter Switch to multi-line editingctrl-enter 运行

其他命令

:sysinfo :server :schema

节点和关系 建立之前最好先查找一下是否已经存在这个节点,如果已经存在,建立关系时使用查找到的节点,而不要新建,否则会出现一个新的节点

批量导入 一条条建立关系和节点速度并不快,条件合适应使用 Neo4j 的批量导入功能

数据内容

图数据库的本质是为了 方便查找节点之间关系的,而不是为了存储数据因此向一个节点或者关系里面插入很多其余无关的数据是完全没有必要的,会很大程度浪费硬盘资源,在检索的时候也会消耗更多的时间 Cypher Basic Cypher Neo4j 图查询 / 创建语言,描述 找什么,而不是 怎么找CREATE 创建节点// 语法规则 CREATE (节点名: 标签 {节点属性}) CREATE (ee:Person { name: "Emil", from: "Sweden", klout: 99 }) DELETE 删除当前所有节点 / 关系MATCH(n:Person) DETACH DELETE n MATCH 查找节点或关系// 语法规则 MATCH (匹配出的变量名 : 匹配的标签) WHERE 过滤结果 RETURN 返回特定结果 MATCH (pp:Person) WHERE pp.name = "Emil" RETURN pp; CREATE 后面直接用 MATCH 时,需要 WITHcreate (ee:Person {name: "Emil", from: "Sweden", klout: 99}) with ee match (pp:Person) where pp.name="Emil" return pp [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h76yqoFF-1678944724460)(images/neo4j_match.jpg)]CREATE relationships 创建关系// 语法规则 CREATE (节点名 1)-[:关系名 {关系属性}]->(节点名 2) create (ee:Person {name: "Emil", from: "Sweden", klout: 99}) create (et:Person {name: "et"}) create (et)-[:KNOWS {by: "swimming"}]->(ee) return ee, et [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sojDwE7C-1678944724460)(images/neo4j_relation.jpg)]创建多个节点以及关系create (ee:Person {name: "Emil", from: "Sweden", klout: 99}) WITH ee MATCH (pp:Person) WHERE pp.name="Emil" CREATE (js:Person {name: "Johan", from: "Sweden", learn: "surfing"}), (ir: Person {name: "Ian", from: "Belgium", title: "author"}), (rvb: Person {name: "Rik", from: "England", pet: "Orval"}), (ally: Person {name: "Allison", from: "California", hobby: "surfing"}), (ee)-[:KNOWS {since: 2001}]->(js), (ee)-[:KNOWS {rating: 5}]->(ir), (js)-[:KNOWS]->(ir), (js)-[:KNOWS]->(rvb), (ir)-[:KNOWS]->(js), (ir)-[:KNOWS]->(ally), (rvb)-[:KNOWS]->(ally) RETURN ee, js, ir, rvb, ally [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8EMfqLny-1678944724460)(images/neo4j_create_relations.jpg)]MATCH relationships 匹配关系// 语法规则 MATCH (匹配出的变量名 : 匹配的标签) -[:关系]-(匹配到的关系名) WHERE 过滤结果 RETURN 返回特定结果 // pattern can be used to find Emil's friends MATCH (ee:Person)-[:KNOWS]-(friends) WHERE ee.name = "Emil" RETURN ee, friends [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TqZPrpm8-1678944724460)(images/neo4j_match_pattern_knows.jpg)]Recommendations 匹配关系进行推荐// Recommd frind by "surfing" MATCH (js:Person)-[:KNOWS]-()-[:KNOWS]-(surfer) WHERE js.name = "Johan" AND surfer.hobby = "surfing" RETURN DISTINCT surfer [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SbzMvtJD-1678944724460)(images/neo4j_recommdation.jpg)] () empty 表示忽略这些匹配到的节点DISTINCT because more than one path will match the pattern EXPLAIN / PROFILE 显示匹配过程PROFILE MATCH (js:Person)-[:KNOWS]-()-[:KNOWS]-(surfer) WHERE js.name = "Johan" AND surfer.hobby = "surfing" RETURN DISTINCT surfer [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hiD8k0ul-1678944724461)(images/neo4j_explain.jpg)] MATCH 查询 匹配 Node() (pp) (:Person) (pp:Person) (pp:Person {name: "Emil"}) 匹配 Relationship--> -[role]-> -[:KNOWS]-> -[role:KNOWS]-> -[role:KNOWS {since: 2001}]-> -[:KNOWS*2]-> // Length 2 relationship -[:KWONS*1..3]-> // Variable length relationships -[role:ACTED|:DIRECTED]-> // deprecated, use UNION instead 基本查询// 查询所有节点 MATCH (n) RETURN n // 查询所有有连接的节点 MATCH (n)-->(m) RETURN n, m // 查询所有有外向连接的节点 MATCH (n)-->( ) RETURN n // 查询所有关系类型 MATCH ()-[rel]->() RETURN type(rel) // 查询所有用户名与所有的关系 MATCH (aa)-[rr]->(bb) RETURN aa.name AS From, type(rr) AS Related, bb.name AS To 条件查询// 查询指定用户的关系 MATCH (aa:Person {name:"Emil"})-->(bb) RETURN aa, bb // 使用 WHERE 指定条件 MATCH (aa:Person)-->(bb) WHERE aa.name="Emil" RETURN aa, bb // 名字中含有 "a" MATCH (aa:Person) WHERE aa.name =~ ".*a.*" RETURN aa // 查询关系长度 1 到 3 的节点 MATCH (aa)-[:KNOWS*1..3]->(bb) WHERE aa.name="Emil" RETURN aa, bb // 查询 同时认识一个人,互相之间又不认识的人 MATCH (aa)-[:KNOWS]->(bb)(bb), (cc)-[:KNOWS]->(bb) WHERE NOT (aa)--(cc) RETURN aa, bb, cc // 删除没有 name 属性的节点 MATCH (aa:Person) WHERE NOT exists(aa.name) DETACH DELETE aa 定义 path [ ??? ]MATCH p=(a)-[:KNOWS]->(m)(m)(m)(m), p2=(d)-[:KNOWS]->(m) RETURN p1, p2 可变长度关系查询// 长度为 2 的关系 MATCH p = (aa)-[:KNOWS*2]->(bb) RETURN aa.name, bb.name // 长度 1 到 3 的关系 MATCH p = (aa)-[:KNOWS*1..3]->(bb) RETURN aa.name, bb.name // 不推荐将可变长度关系绑定到一个变量,使用 path MATCH p = (aa)-[:KNOWS*1..3]->(bb) WITH *, relationships(p) AS rr RETURN rr MATCH p = (aa)-[:KNOWS*1..3]->(bb) WITH *, relationships(p) AS rr RETURN aa.name, size(rr), bb.name MATCH p = (aa)-[:KNOWS*1..3]->(bb) WITH *, relationships(p) AS rr RETURN aa.name, length(rr), bb.name // 长度为 0 的关系,关系的起止是同一个节点 MATCH (aa)-[:KNOWS*0..1]-(bb) RETURN aa MATCH - CREATE - RETURNMATCH (ir:Person {name: "Ian"}), (em: Person {name: "Emil"}) CREATE (ir)-[:KNOWS]->(em) RETURN ir, em WITH WITH 将 上一个命令的输出 与 下一个命令的输入 结合起来,工作原理类似 RETURN,只是不返回结果CREATE - WITH - MATCHCREATE (al:Person {name: "Alice", age: 21}) CREATE (bb:Person {name: "Bob", age: 23}) CREATE (al)-[:KNOWS]->(bb) WITH al, bb MATCH (n: Person {name: "Alice"}) RETURN n Actor - Movie 数据库中的应用MATCH (person:Person)-[:ACTED_IN]->(m:Movie) WITH person, count(*) AS appearances, collect(m.title) AS movies WHERE appearances > 1 RETURN person.name, appearances, movies // Output +------------------------------------------------------------+ | person.name | appearances | movies | +------------------------------------------------------------+ | "Tom Hanks" | 2 | ["Cloud Atlas","Forrest Gump"] | +------------------------------------------------------------+ 1 row INDEX 索引 Neo4j 2.0 版本在标签的基础上引入了索引,可以对标签进行限制和索引 尽量使用 schema index,而不要使用旧版本的索引索引可以很大程度上降低大规模数据的查询速度最好在插入数据之前就建立好索引,否则索引的建立会很消耗时间 索引 和其他 RDBMS 的定义相类似,主要用于提升节点查询的性能,即有助于数据完整性检查,也有利于优化 Cypher创建索引 索引建立后,随后的查询中出现具有索引的属性时,将自动使用索引CREATE INDEX ON :() // 初始化数据,不使用索引查询 CREATE (al:Person {name: "Alice", age: 21}) CREATE (bb:Person {name: "Bob", age: 23}) CREATE (al)-[:KNOWS {period_year: 6}]->(bb) PROFILE MATCH (n:Person) WHERE n.name="Alice" RETURN n [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zmUAnsgm-1678944724461)(images/neo4j_index_1.jpg)]// 创建索引查询 CREATE INDEX ON :Person(name) PROFILE MATCH (n:Person) WHERE n.name="Alice" RETURN n [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFynTsM4-1678944724461)(images/neo4j_index_2.jpg)]:schema 显示当前的索引:schema CALL db.indexes // 显示图数据库中的元模型 CALL db.schema 删除索引DROP INDEX ON :() DROP INDEX ON :Person(name) USING INDEX 显式指定索引 必须首先创建索引才能显式指定USING INDEX :(Property) USING SCAN : MATCH (n:Person) USING INDEX n:Person(name) WHERE n.name="Alice" RETURN(n) MATCH (n:Person) USING SCAN n:Person WHERE n.name="Alice" RETURN(n) 最短路径 Shortest path Single shortest path 函数 shortestPath 查找两个节点间的一条最短路径// 查找两个节点间的最短路径 MATCH (aa:Person {name: "Ian"}), (bb:Person {name: "Rik"}), p=shortestpath((aa)-[*..5]-(bb)) RETURN p [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M8SDWS3P-1678944724461)(images/neo4j_shortestpath_single.jpg)]All shortest paths 函数 allShortestPaths 查找两个节点间的所有最短路径// 查找两个节点间的所有最短路径 MATCH (aa:Person {name: "Ian"}), (bb:Person {name: "Rik"}), p=allShortestPaths((aa)-[*..5]-(bb)) RETURN p [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gmUYYpuq-1678944724461)(images/neo4j_shortestpath_all.jpg)]// 过滤 ANY MATCH (aa:Person {name: "Ian"}), (bb:Person {name: "Rik"}), p=allShortestPaths((aa)-[*..5]-(bb)) WHERE ANY (r IN relationships(p) WHERE type(r)="KNOWS") RETURN p // 过滤 NONE MATCH (aa:Person {name: "Ian"}), (bb:Person {name: "Rik"}), p=allShortestPaths((aa)-[*..5]-(bb)) WHERE NONE (r IN relationships(p) WHERE type(r)="KNOWS") RETURN p Movie Graph Create 创建 Movie Graph 演员-电影 图数据库,演员参演电影的关系图:play movie-graph neo4j_movie_graph.cypher// 示例 CREATE (YouveGotMail:Movie {title:"You've Got Mail", released:1998, tagline:'At odds in life... in love on-line.'}) CREATE (ParkerP:Person {name:'Parker Posey', born:1968}) CREATE (DaveC:Person {name:'Dave Chappelle', born:1973}) CREATE (SteveZ:Person {name:'Steve Zahn', born:1967}) CREATE (TomH:Person {name:'Tom Hanks', born:1956}) CREATE (NoraE:Person {name:'Nora Ephron', born:1941}) CREATE (TomH)-[:ACTED_IN {roles:['Joe Fox']}]->(YouveGotMail), (MegR)-[:ACTED_IN {roles:['Kathleen Kelly']}]->(YouveGotMail), (GregK)-[:ACTED_IN {roles:['Frank Navasky']}]->(YouveGotMail), (ParkerP)-[:ACTED_IN {roles:['Patricia Eden']}]->(YouveGotMail), (DaveC)-[:ACTED_IN {roles:['Kevin Jackson']}]->(YouveGotMail), (SteveZ)-[:ACTED_IN {roles:['George Pappas']}]->(YouveGotMail), (NoraE)-[:DIRECTED]->(YouveGotMail)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SeVe0uDA-1678944724461)(images/neo4j_movie_create.jpg)]

Find 查找 查找演员名 “Tom Hanks”MATCH (tom {name: "Tom Hanks"}) RETURN tom 查找电影名 “Cloud Atlas”MATCH (cloudAtlas {title: "Cloud Atlas"}) RETURN cloudAtlas 查找 10 个人MATCH (people:Person) RETURN people.name LIMIT 10 查找 90 年代的电影 1990 = 1990 AND nineties.released title: "Cloud Atlas"})name:"Tom Hanks"})-[:ACTED_IN]->(m)title: "Cloud Atlas"}) RETURN people.name, Type(relatedTo), relatedTo MATCH (people:Person)-[relatedTo]-(ca:Movie {title: "Cloud Atlas"}) RETURN people, relatedTo, ca [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ipRL3sR-1678944724462)(images/neo4j_movie_ca_relation.jpg)] Solve 最短路径 Bacon Path 与 “Kevin Bacon” 4 层关系以内的演员和电影MATCH (bacon:Person {name:"Kevin Bacon"})-[*1..4]-(hollywood) RETURN DISTINCT hollywood MATCH (bacon:Person {name:"Kevin Bacon"})-[*1..2]-(hollywood) RETURN DISTINCT hollywood, bacon [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1WFtdCl-1678944724462)(images/neo4j_movie_becon_relation.jpg)]Bacon path “Kevin Bacon” 与 “Meg Ryan” 之间的最短路径MATCH p=shortestPath( (bacon:Person {name:"Kevin Bacon"})-[*]-(meg:Person {name:"Meg Ryan"}) ) RETURN p [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VDqiGas9-1678944724462)(images/neo4j_movie_becon_path.jpg)] Recommend 推荐 为 “Tom Hanks” 推荐新的合作演员 查找 Tom Hanks 合作过的演员,新的合作演员与这些演员合作过Tom Hanks 没有与推荐的演员合作过 MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)(m2)()name:"Tom Cruise"}) RETURN tom, m, coActors, m2, cruise [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQsheinx-1678944724462)(images/neo4j_movie_recomm_tt.jpg)] Clean up 删除电影数据 关系存在的时候不能删除节点,必须同时删除节点与关系 // Delete all Movie and Person nodes, and their relationships MATCH (n) DETACH DELETE n // Prove that the Movie Graph is gone MATCH (n) RETURN n LOAD CSV 加载 Persons Movies 数据 导入 persons.csvLOAD CSV WITH HEADERS FROM "http://neo4j.com/docs/developer-manual/3.4/csv/import/persons.csv" AS csvLine CREATE (p:Person { id: toInteger(csvLine.id), name: csvLine.name }) idname1Charlie Sheen2Oliver Stone3Michael Douglas4Martin Sheen5Morgan Freeman导入 movies.csv 使用 MERGE 避免创建重复数据// 在使用 MERGE / MATCH 时,应首先创建索引 CREATE INDEX ON :Country(name) LOAD CSV WITH HEADERS FROM "http://neo4j.com/docs/developer-manual/3.4/csv/import/movies.csv" AS csvLine MERGE (country:Country { name: csvLine.country }) CREATE (movie:Movie { id: toInteger(csvLine.id), title: csvLine.title, year:toInteger(csvLine.year)}) CREATE (movie)-[:MADE_IN]->(country) idtitlecountryyear1Wall StreetUSA19872The American PresidentUSA19953The Shawshank RedemptionUSA1994创建索引 使用 id 作为索引,只在关联关系时使用,使用 CREATE CONSTRAINT ON ... ASSERT ... IS UNIQUE 创建 唯一性约束,同时会创建 唯一性索引CREATE CONSTRAINT ON (person:Person) ASSERT person.id IS UNIQUE CREATE CONSTRAINT ON (movie:Movie) ASSERT movie.id IS UNIQUE 导入 roles.csv 创建关系,USING PERIODIC COMMIT 在加载大型 csv 文件时,通知 Neo4j 会创建大量的数据USING PERIODIC COMMIT 500 LOAD CSV WITH HEADERS FROM "https://neo4j.com/docs/developer-manual/3.4/csv/import/roles.csv" AS csvLine MATCH (person:Person { id: toInteger(csvLine.personId)}), (movie:Movie { id: toInteger(csvLine.movieId)}) CREATE (person)-[:PLAYED { role: csvLine.role }]->(movie) personIdmovieIdrole11Bud Fox41Carl Fox31Gordon Gekko42A.J. MacInerney32President Andrew Shepherd53Ellis Boyd ‘Red’ Redding删除临时索引 movie / person 的索引在创建完关系后不再需要DROP CONSTRAINT ON (person:Person) ASSERT person.id IS UNIQUE DROP CONSTRAINT ON (movie:Movie) ASSERT movie.id IS UNIQUE MATCH (n) WHERE n:Person OR n:Movie REMOVE n.id Northwind Graph Northwind 数据表结构

RDBMS 关系数据库管理系统 Relational Database Management System

Northwind Graph 将一个传统的关系型数据库转化为图数据库

:play northwind-graph

Product Catalog 产品类别,包含了 产品 product - 类别 categories - 供应商 suppliers 的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ml7VfklO-1678944724463)(images/neo4j_nw_product_cata.jpg)]

products.csv

productIDproductNamesupplierIDcategoryIDquantityPerUnitunitPriceunitsInStockunitsOnOrderreorderLeveldiscontinued1Chai1110 boxes x 20 bags183901002Chang1124 - 12 oz bottles1917402503Aniseed Syrup1212 - 550 ml bottles101370250

categories.csv

categoryIDcategoryNamedescriptionpicture1BeveragesSoft drinks, coffees, teas, beers, and ales0x151…2CondimentsSweet and savory sauces, relishes, spreads, and seasonings0x151…3ConfectionsDesserts, candies, and sweet breads0x151…

suppliers.csv

supplierIDcompanyNamecontactNamecontactTitleaddresscityregionpostalCodecountryphonefaxhomePage1Exotic LiquidsCharlotte CooperPurchasing Manager49 Gilbert St.LondonNULLEC1 4SDUK(171) 555-2222NULLNULL2New Orleans Cajun DelightsShelley BurkeOrder AdministratorP.O. Box 78934New OrleansLA70117USA(100) 555-4822NULL#CAJUN.HTM#3Grandma Kelly’s HomesteadRegina MurphySales Representative707 Oxford Rd.Ann ArborMI48104USA(313) 555-5735(313) 555-3349NULL

Customer Orders 客户订单,包含了 Custom - Order 对应关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NWxJO1Di-1678944724463)(images/neo4j_nw_customor_orders.jpg)]

customers.csv

customerIDcompanyNamecontactName…ALFKIAlfreds FutterkisteMaria Anders…ANATRAna Trujillo Emparedados y heladosAna Trujillo…ANTONAntonio Moreno TaqueríaAntonio Moreno…

orders.csv

orderIDcustomerIDemployeeIDorderDate…10248VINET51996-07-04 00:00:00.000…10249TOMSP61996-07-05 00:00:00.000…10250HANAR41996-07-08 00:00:00.000…

OrderDetail 包含了 Order - Product 的对应关系

orderIDproductIDunitPricequantitydiscount10248111412010248429.8100102487234.850 加载 Product Catalog CSV 文件 LOAD CSV:help cypher LOAD CSV 加载 products.csv / categories.csv / suppliers.csv 文件// products.csv LOAD CSV WITH HEADERS FROM "http://data.neo4j.com/northwind/products.csv" AS row CREATE (n:Product) SET n = row, n.unitPrice = toFloat(row.unitPrice), n.unitsInStock = toInteger(row.unitsInStock), n.unitsOnOrder = toInteger(row.unitsOnOrder), n.reorderLevel = toInteger(row.reorderLevel), n.discontinued = (row.discontinued "0") // categories.csv LOAD CSV WITH HEADERS FROM "http://data.neo4j.com/northwind/categories.csv" AS row CREATE (n:Category) SET n = row // suppliers.csv LOAD CSV WITH HEADERS FROM "http://data.neo4j.com/northwind/suppliers.csv" AS row CREATE (n:Supplier) SET n = row Create indexes 创建索引CREATE INDEX ON :Product(productID) CREATE INDEX ON :Category(categoryID) CREATE INDEX ON :Supplier(supplierID) 创建 Product Catalog 关系图

products / categories / suppliers 通过 ID 键值 联系起来

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NnXQ1NYY-1678944724463)(images/neo4j_nw_product_cata_relation.jpg)]

创建关系 relationships

:help cypher MATCH MATCH (p:Product),(c:Category) WHERE p.categoryID = c.categoryID CREATE (p)-[:PART_OF]->(c) MATCH (p:Product),(s:Supplier) WHERE p.supplierID = s.supplierID CREATE (s)-[:SUPPLIES]->(p)

查找每个供应商 supplier 提供的产品类别 categories

MATCH (s:Supplier)-->(:Product)-->(c:Category) RETURN s.companyName as Company, collect(distinct c.categoryName) as Categories CompanyCategories“Lyngbysild”[“Seafood”]“G’day”[“Grains/Cereals”, “Meat/Poultry”, “Produce”]“Tokyo Traders”[“Meat/Poultry”, “Produce”, “Seafood”]

查找 “Produce” 类别的供应商

MATCH (c:Category {categoryName:"Produce"})(p) SET details = row, details.quantity = toInteger(row.quantity) 综合查询MATCH (cust:Customer)-[:PURCHASED]->(:Order)-[o:ORDERS]->(p:Product), (p)-[:PART_OF]->(c:Category {categoryName:"Produce"}) RETURN DISTINCT cust.contactName as CustomerName, SUM(o.quantity) AS TotalProductsPurchased Neo4j CQL 命令格式 Neo4j CQL 简介

CQL代表Cypher查询语言,遵循SQL语法

常用的 Neo4j CQL 命令

CQL 命令用法CREATE 创建创建节点,关系和属性MATCH 匹配检索有关节点,关系和属性数据RETURN 返回返回查询结果WHERE 过滤提供条件过滤检索数据DELETE 删除删除节点和关系REMOVE 移除删除节点和关系的属性ORDER BY以…排序 排序检索数据SET 设置添加或更新标签

常用的 Neo4j CQL 函数

定制列表功能用法String 字符串用于使用 String 字面量Aggregation 聚合用于对 CQL 查询结果执行一些聚合操作Relationship 关系用于获取关系的细节,如 startnode,endnode 等

Neo4j CQL 数据类型

CQL数据类型用法boolean布尔文字:true,falsebyte8位整数short16位整数int32位整数long64位整数float32位浮点数double64位浮点数char16位字符String字符串 CREATE 创建 节点 / 关系 / 标签// 创建没有属性的节点 CREATE (:) // 创建多个标签的节点 CREATE (::.....:) // 创建具有属性的节点 CREATE ( : { : ........ : } ) // 创建节点间的关系 CREATE (:)- [(:)] ->(:) node-name 节点名,不能用来访问节点详细信息label-name 标签名,可以用来访问节点详细信息 MATCH 从数据库获取有关节点,关系和属性的数据MATCH (:) MATCH (: {: }) // MATCH WHERE RETURN / DELETE / CREATE / ... MATCH (:) WHERE RETURN . // Variable length relationships MATCH ()-[:TYPE*minHops..maxHops]->() RETURN , () 不能单独使用 MATCH 从数据库检索数据,配合使用 RETURN / DELETE / CREATE 等 RETURN 返回 节点 / 关系的 某些 / 全部 属性RETURN ., . RETURN . AS , . AS 配合 MATCH 使用可以配合使用 ORDER BY / AS / LIMIT / SKIP 等子句 WHERE

WHERE子句来过滤MATCH查询的结果

// 单一条件 WHERE // 布尔运算符 WHERE // MATCH WHERE CREATE,创建两个现有节点之间的关系 MATCH (:),(:) WHERE CREATE ()-[: {}]->()

正则表达式匹配

// 含有字母 a WHERE =~ ".*a.*"

boolean-operator 布尔运算符

布尔运算符描述AND与OR或NOT非XOR异或

comparison-operator 比较运算符

布尔运算符描述=等于不等于大于=大于或等于=~正则表达式匹配

Predicate functions 判定函数 通常用于过滤一组结果

判定函数描述语法All所有都为 Trueall(variable IN list WHERE predicate)ANY有一个为 Trueany(variable IN list WHERE predicate)EXISTS存在exists(pattern-or-property)NONE所有都为 Falsenone(variable IN list WHERE predicate)SINGLE只有一个为 Truesingle(variable IN list WHERE predicate)MATCH p =(a)-[*1..3]->(b) WHERE a.name = 'Alice' AND b.name = 'Daniel' AND ALL (x IN nodes(p) WHERE x.age > 30) RETURN p MATCH (a) WHERE a.name = 'Eskil' AND ANY (x IN a.array WHERE x = 'one') RETURN a.name, a.array MATCH (n) WHERE exists(n.name) RETURN n.name AS name, exists((n)-[:MARRIED]->()) AS is_married MATCH p =(n)-[*1..3]->(b) WHERE n.name = 'Alice' AND NONE (x IN nodes(p) WHERE x.age = 25) RETURN p MATCH p =(n)-->(b) WHERE n.name = 'Alice' AND SINGLE (var IN nodes(p) WHERE var.eyes = 'blue') RETURN p DELETE 用于删除节点和关联关系DELETE DELETE ,, DETACH 删除节点同时删除相关关系MATCH (: {: }) DETACH DELETE REMOVE 用于删除标签和属性// 删除节点/关系的属性 REMOVE ., . // 删除节点/关系的标签 REMOVE :, : SET 向现有 节点 / 关系 添加 / 更新 属性值SET ., . ORDER BY 对 MATC H查询返回的结果进行排序// 默认按升序对行进行排序,DESC 指定降序排列 ORDER BY ., . [DESC] UNION UNION 将两组结果中的公共行组合并返回到一组结果中,不返回重复行 UNION UNION ALL 将两组结果中的公共行组合并返回到一组结果中,返回重复行 UNION ALL 限制 组合的两个结果集的名字必须匹配,列名称 与 列的数据类型 应该是相同的可使用 AS 统一返回的列名称 AS 用于给一些列起别名,如 RETURN 的返回结果,或用于 UNION 时统一列名MATCH (:) RETURN . AS , . AS UNION MATCH (:) RETURN . AS , . AS LIMIT 过滤或限制查询返回的行数,取 顶部 的 number 行LIMIT SKIP 过滤或限制查询返回的行数,取 底部 的 number 行SKIP MERGE MERGE 命令是 CREATE 命令和 MATCH 命令的组合 搜索给定模式,如果存在,则返回结果如果不存在,则创建新的节点 / 关系并返回结果 MERGE (: { :=”, “=~” 其他数据库特性 触发器 Trigger写入锁 Write lock显示数据库元模型 metadata数据轮廓 Data profiling管理索引和限制对节点和关系并发操作的支持:原子性 py2neo 链接 The Py2neo Handbookpy2neo github Node Relation Property Neo4j 里面最重要的两个数据结构就是 节点 Node 和 关系 Relationship,可以通过 Node 或 Relationship 对象创建class Node(Entity) __init__(self, *labels, **properties) class Relationship(Entity) __init__(self, *nodes, **properties) Relationship 类 创建关系from py2neo import Node, Relationship a = Node('Person', name='Alice') b = Node('Person', name='Bob') r = Relationship(a, 'KNOWS', b) print(a, b, r) # (:Person {name: 'Alice'}) (:Person {name: 'Bob'}) (Alice)-[:KNOWS {}]->(Bob) 指定 typeWORKS_WITH = Relationship.type('WORKS_WITH') ab = WORKS_WITH(a, b) ab # Out[12]: (Alice)-[:WORKS_WITH {}]->(Bob) 类继承c = Node("Person", name="Carol") class WorkWith(Relationship): pass ac = WorkWith(a, c) ac # Out[8]: (Alice)-[:WorkWith {}]->(Carol) type(ac) # Out[9]: __main__.WorkWith Node 和 Relationship 都继承了 PropertyDict 类,它可以赋值很多属性,类似于字典的形式a['age'] = 20 b['age'] = 21 r['time'] = '2017/08/31' print(a, b, r) # (:Person {age: 20, name: 'Alice'}) (:Person {age: 21, name: 'Bob'}) (Alice)-[:KNOWS {time: '2017/08/31'}]->(Bob) len(a) # Out[32]: 2 len(r) # Out[33]: 1 dict(a) # Out[35]: {'name': 'Alice', 'age': 20} dict(r) # Out[36]: {'time': '2017/08/31'} Node Relationship 的其他方法 Node 标签操作 labels / add_label / remove_label / clear_labels / update_labels / has_labela.labels # Out[37]: :Person a.add_label('MAN') a.labels # Out[51]: :MAN:Person a.clear_labels() a.update_labels(['WOMAN', 'PERSON']) a.labels # Out[61]: :PERSON:WOMAN setdefault 方法赋值默认属性a.setdefault('location', 'Bei Jing') print(a) # (:Person {age: 20, location: 'Bei Jing', name: 'Alice'}) 赋值 location 属性,覆盖默认属性a['location'] = 'Shang Hai' a.setdefault('location', 'Bei Jing') print(a) # (:Person {age: 20, location: 'Shang Hai', name: 'Alice'}) update 方法对属性批量更新data = { 'name': 'Amy', 'age': 21 } a.update(data) print(a) # (:Person {age: 21, location: 'Shang Hai', name: 'Amy'}) Subgraph 子图 Subgraph 子图 是 Node 和 Relationship 的集合,最简单的构造子图的方式是通过关系运算符from py2neo import Node, Relationship s = ab | ac print(list(s.nodes)) # [(:PERSON:WOMAN {age: 21, location: 'Bei Jing', name: 'Amy'}), (:Person {name: 'Carol'}), (:Person {age: 21, name: 'Bob'})] print(list(s.relationships)) # [(Amy)-[:WorkWith {}]->(Carol), (Amy)-[:WORKS_WITH {}]->(Bob)] | / & / - / ^ 取 Subgraph 的并集 / 交集 / 差集 / 异或ss = ab & ac print(list(ss.nodes)) # [(:PERSON:WOMAN {age: 21, location: 'Bei Jing', name: 'Amy'})] print(list(ss.relationships)) # [] labels / nodes / relationships / keys() / types() 分别获取 Subgraph 的属性值s = a | b | r print(s.keys()) # frozenset({'name', 'age', 'location'}) print(list(s.labels)) # ['PERSON', 'Person', 'WOMAN'] print(list(s.nodes)) # [(:PERSON:WOMAN {age: 21, location: 'Bei Jing', name: 'Amy'}), (:Person {name: 'Carol'}), (:Person {age: 21, name: 'Bob'})] print(list(s.relationships)) # [(Amy)-[:WorkWith {}]->(Carol), (Amy)-[:WORKS_WITH {}]->(Bob)] print(s.types()) # frozenset({'WorkWith', 'WORKS_WITH'}) Walkable Walkable 增加了遍历信息的 Subgraph,通过 + 构建一个 Walkable 对象from py2neo import Node, Relationship a = Node('Person', name='Alice') b = Node('Person', name='Bob') c = Node('Person', name='Mike') ab = Relationship(a, "KNOWS", b) ac = Relationship(a, "KNOWS", c) w = ab + Relationship(b, "LIKES", c) + ac print(type(w)) # print(w.nodes) # ((:Person {name: 'Alice'}), (:Person {name: 'Bob'}), (:Person {name: 'Mike'}), (:Person {name: 'Alice'})) print(w.relationships) # ((Alice)-[:KNOWS {}]->(Bob), (Bob)-[:LIKES {}]->(Mike), (Alice)-[:KNOWS {}]->(Mike)) walk 方法实现遍历from py2neo import walk for item in walk(w): print(item) # (:Person {name: 'Alice'}) # (Alice)-[:KNOWS {}]->(Bob) # (:Person {name: 'Bob'}) # (Bob)-[:LIKES {}]->(Mike) # (:Person {name: 'Mike'}) # (Alice)-[:KNOWS {}]->(Mike) # (:Person {name: 'Alice'}) start_node / end_node / nodes / relationships 获取 Walkable 的属性值print(w.start_node) # (:Person {name: 'Alice'}) print(w.end_node) # (:Person {name: 'Alice'}) print(w.nodes) # ((:Person {name: 'Alice'}), (:Person {name: 'Bob'}), (:Person {name: 'Mike'}), (:Person {name: 'Alice'})) print(w.relationships) # ((Alice)-[:KNOWS {}]->(Bob), (Bob)-[:LIKES {}]->(Mike), (Alice)-[:KNOWS {}]->(Mike)) start_node 与 end_node 是同一个 Graph

Graph 代表了 Neo4j 的图数据库,提供了许多方法来操作 Neo4j 数据库

默认连接参数 bolt://localhost:7687 neo4j / password

KeywordDescriptionTypeDefaultauthA 2-tuple of (user, password)tuple(‘neo4j’, ‘password’)hostDatabase server host namestr‘localhost’passwordPassword to use for authenticationstr‘password’portDatabase server portint7687schemeUse a specific URI schemestr‘bolt’secureUse a secure connection (TLS)boolFalseuserUser to authenticate asstr‘neo4j’user_agentUser agent to send for all connectionsstr(depends on URI scheme)

初始化 使用默认的连接,匹配自己的用户名密码

neo4j-client -u neo4j -p 123456 bolt://localhost:7687

用户名 neo4j 密码 123456

from py2neo import Graph # Bolt graph_1 = Graph(auth=('neo4j', '123456')) graph_2 = Graph("bolt://localhost:7687", auth=('neo4j', '123456')) graph_3 = Graph(scheme='bolt', host='localhost', port=7687, user='neo4j', password='123456') graph_1.database # Out[121]: # http 初始化的 graph 不能 create,必须用 bold graph create 过 graph_4 = Graph("http://localhost:7474") graph_5 = Graph(scheme='http', host="localhost", port=7474)

begin 创建一个新的 Transaction,Graph 很多方法实际执行的是 Transaction 方法

from py2neo import Node, Relationship, Graph a = Node('Person', name='Alice') b = Node('Person', name='Bob') c = Node('Person', name='Carol') ab = Relationship(a, 'KNOWS', b) ac = Relationship(a, 'KNOWS', c) bc = Relationship(b, 'KNOWS', c) s = ab | ac | bc # 使用 Transaction.create tx = graph.begin() tx.create(s) tx.commit()

create 方法传入 Subgraph 对象来将关系图添加到数据库中

# 使用 Graph.create graph = Graph(auth=('neo4j', '123456')) graph.create(s)

delete / delete_all 删除子图,实际执行 Transaction.delete

删除 节点 同时会删除所有对应的 关系删除 关系 同时会删除所有对应的 节点 aa = graph.nodes.match("Person", name="Alice").first() ar = graph.relationships.match(nodes=[aa], r_type="KNOWS").first() graph.delete(ar) graph.delete(aa) graph.delete_all() list(graph.nodes.match())

清除 清除后如果要重新创建,需要重新初始化 Node / Relationship

graph.run('MATCH (p:Person) DETACH DELETE p')

exists 检验存在一个节点,实际执行 Transaction.exists

graph.exists(ab) # Out[8]: True graph.match_one(r_type='KNOWS') # Out[9]: (Alice)-[:KNOWS {}]->(Bob) [tt.data() for tt in graph.run('MATCH (p:Person) return p')] # Out[43]: [{'p': (_4299:Person {name: 'Alice'})}, # {'p': (_4300:Person {name: 'Carol'})}, # {'p': (_4301:Person {name: 'Bob'})}]

match / match_one 匹配并返回所有 / 一个 Relationship

match(nodes=None, r_type=None, limit=None) match_one(nodes=None, r_type=None) # Nodes must be supplied as a Sequence or a Set alice = graph.nodes.match('Person', name='Alice').first() for rel in graph.match((alice, ), r_type="KNOWS"): print(rel.end_node["name"]) # Bob # Carol graph.match_one(r_type='KNOWS') # Out[89]: (Alice)-[:KNOWS {}]->(Bob)

nodes.match 查找 Node

# py2neo.matching.NodeMatcher 的实例 match(*labels, **properties) graph.nodes.match("Person", name="Alice").first() # Out[152]: (_4299:Person {name: 'Alice'})

nodes.get 根据 ID 获取节点

graph.nodes[4299] # Out[153]: (_4299:Person {name: 'Alice'}) graph.nodes.get(4299) # Out[154]: (_4299:Person {name: 'Alice'})

relationships.match 查找 Relationship

# py2neo.matching.RelationshipMatcher 的实例 match(nodes=None, r_type=None, **properties) list(graph.relationships.match(r_type="KNOWS")) # Out[97]: [(Alice)-[:KNOWS {}]->(Bob), # (Alice)-[:KNOWS {}]->(Carol), # (Bob)-[:KNOWS {}]->(Carol)] # nodes is a list alice = graph.nodes.match('Person', name='Alice').first() graph.relationships.match(nodes=[alice], r_type="KNOWS").first() # Out[108]: (Alice)-[:KNOWS {}]->(Bob)

pull / push 获取 / 更新 Node 属性

aa = graph.nodes.match("Person", name="Alice").first() aa["age"] = 21 graph.push(aa) graph.nodes.match("Person", name="Alice").first() # Out[123]: (_4299:Person {age: 21, name: 'Alice'})

run 直接执行 CQL 命令

[tt.data() for tt in graph.run('MATCH (p:Person) return p')] # Out[43]: [{'p': (_77:Person {name: 'Alice'})}, {'p': (_102:Person {name: 'Bob'})}] from py2neo import Graph graph_1 = Graph(auth=('neo4j', '123456')) graph_1.run("UNWIND range(1, 3) as n RETURN n, n * n as n_sq").to_table() # Out[109]: # n | n_sq # ---|------ # 1 | 1 # 2 | 4 # 3 | 9

separate 删除关系,实际执行 Transaction.separate

aa = graph.nodes.match("Person", name="Alice").first() ar = graph.relationships.match(nodes=[aa], r_type="KNOWS").first() graph.separate(ar) Record Record 记录,表示匹配到的一条数据,扩展的元组与字典len 记录的长度# run 执行 cypher 命令返回 Cursor rr = graph.run('MATCH (n) RETURN n') type(rr) # Out[363]: py2neo.database.Cursor # 遍历 rr 的值是 record rr.forward() # Out[364]: 1 tt = rr.current type(tt) # Out[366]: py2neo.data.Record len(tt) # Out[371]: 1 dict / data 转化为字典dict(tt) # Out[372]: {'n': (_4324:Person {name: 'Bob'})} tt.data() # Out[376]: {'n': (_4324:Person {name: 'Bob'})} keys / values / items / get 类似字典方法tt.keys() # Out[377]: ['n'] tt.values() # Out[378]: [(_4324:Person {name: 'Bob'})] tt.items() # Out[379]: [('n', (_4324:Person {name: 'Bob'}))] tt.get('n') # Out[380]: (_4324:Person {name: 'Bob'}) to_subgrapth 转化为子图tt.to_subgraph() # Out[381]: (_4324:Person {name: 'Bob'}) aa = tt.to_subgraph() aa['name'] # Out[383]: 'Bob' Table Table 表,包含 record 的集合,通常是 cypher 请求的返回值,扩展的列表tt = graph.run('MATCH (n) RETURN n.name, n.age').to_table() tt # Out[468]: # n.name | n.age # --------|------- # Bob | null # Carol | null # Alice | null write / write_html / write_separated_values / write_csv / write_tsv 将数据写入到文件 Transaction transaction 是多条 cypher 命令的包装组合,graph 的许多方法需要调用到 transactionfrom py2neo import Graph, Node, Relationship g = Graph() tx = g.begin() a = Node("Person", name="Alice") tx.create(a) b = Node("Person", name="Bob") ab = Relationship(a, "KNOWS", b) tx.create(ab) tx.commit() g.exists(ab) # Out[181]: True finished 返回该 transaction 是否已执行完成tx.finished() # Out[182]: True rollback 回滚上次 transaction 的操作 Cursor Cursor 游标,Record 记录的流式处理,所有的 cursor 都是 forward-only,从第一个节点之前开始,只能前向遍历rr = graph.run('MATCH (n) RETURN n') type(rr) # Out[404]: py2neo.database.Cursor for tt in rr: print('type = %s, name = %s' % (type(tt), tt['n']['name'])) # type = , name = Bob # type = , name = Carol # type = , name = Alice forward 与 current,用于遍历 cursor,forward 有值返回 1,否则返回 0,current 表示当前的 recordrr = graph.run('MATCH (n) RETURN n') while rr.forward(): print(rr.current['n']['name']) # Bob # Carol # Alice next 遍历,python 内置方法rr = graph.run('MATCH ()-[rr:KNOWS]-() RETURN rr') next(rr)['rr'] # Out[427]: (Alice)-[:KNOWS {}]->(Bob) evaluate 判断是否有下一条,并返回rr = graph.run('MATCH (n) RETURN n') rr.evaluate() # Out[452]: (_4324:Person {name: 'Bob'}) rr.evaluate() # Out[453]: (_4325:Person {name: 'Carol'}) rr.evaluate() # Out[454]: (_4357:Person {name: 'Alice'}) rr.evaluate() == None # Out[456]: True data 返回所有数据,字典格式graph.run('MATCH (n) RETURN n.name, n.age').data() # Out[441]: # [{'n.name': 'Bob', 'n.age': None}, # {'n.name': 'Carol', 'n.age': None}, # {'n.name': 'Alice', 'n.age': None}] to_data_frame / to_series / to_ndarray / to_subgraph / to_table 转化为 dataframe / series / array / 子图 / tablegraph.run('MATCH (n) RETURN n.name, n.age').to_data_frame() # Out[460]: # n.age n.name # 0 None Bob # 1 None Carol # 2 None Alice Errors and Warnings class py2neo.database.GraphError(*args, **kwargs)[source] class py2neo.database.ClientError(*args, **kwargs)[source] # The Client sent a bad request - changing the request might yield a successful outcome. class py2neo.database.DatabaseError(*args, **kwargs)[source] # The database failed to service the request. class py2neo.database.TransientError(*args, **kwargs)[source] # The database cannot service the request right now, retrying later might yield a successful outcome. class py2neo.database.TransactionFinished(*args, **kwargs)[source] # Raised when actions are attempted against a Transaction that is no longer available for use. Matching

NodeMatcher 匹配节点,支持 WHERE 子句 支持的条件

from py2neo import NodeMatcher matcher = NodeMatcher(graph) matcher.match('Person', name='Alice').first() # Out[194]: (_4299:Person {age: 21, name: 'Alice'})

后缀操作符

DescriptionSuffixOperatorExampleExplicit Equal__exact=matcher.match(“Person”, name__exact=”Kevin Bacon”) - MATCH (_:Person) WHERE name = “Kevin Bacon” RETURN _Not Equal__notmatcher.match(“Person”, name__not=”Rick Astley”) - MATCH (_:Person) WHERE _.name “Rick Astley” RETURN _Greater than__gt>matcher.match(“Person”, born__gt=1985) - MATCH (_:Person) WHERE _.born > 1985 RETURN _Greater than or equal to__gte>=matcher.match(“Person”, born__gte=1965) - MATCH (_:Person) WHERE _.born >= 1965 RETURN _Less than__lt(Carol), # (Alice)-[:KNOWS {}]->(Bob), # (Bob)-[:KNOWS {}]->(Carol)] OGM OGM Object Graph Mapping,类似于 ORM,可以实现一个对象和 Node 的关联,类继承 GraphObject,并指定 Property / Label 属性,以及关系 RelatedTo / RelatedFromfrom py2neo.ogm import GraphObject, Property, Label, RelatedTo, RelatedFrom class Movie(GraphObject): __primarykey__ = 'title' title = Property() tag_line = Property("tagline") released = Property() actors = RelatedFrom('Person', 'ACTED_IN') directors = RelatedFrom('Person', 'DIRECTED') producers = RelatedFrom('Person', 'PRODUCED') class Person(GraphObject): __primarykey__ = 'name' name = Property() born = Property() acted_in = RelatedTo('Movie') directed = RelatedTo('Movie') produced = RelatedTo('Movie') Properties 定义一个与节点映射的属性class Person(GraphObject): name = Property() alice = Person() alice.name = 'Alice Smith' alice.name # Out[262]: 'Alice Smith' Labels 定义一个与节点映射的标签,调用结果为 bool 型,表示是否存在该标签class Food(GraphObject): hot = Label() pizza = Food() pizza.hot # Out[265]: False pizza.hot = True pizza.hot # Out[268]: True match / where 结合 Graph 查询# GraphObject.match match(graph, primary_value=None) where(*conditions, **properties) ''' 初始化数据 ''' from py2neo import Graph, Node, Relationship from py2neo.ogm import GraphObject, Property a = Node("Person", name="Alice") b = Node("Person", name="Bob") c = Node('Person', name='Carol') ab = Relationship(a, "KNOWS", b) ac = Relationship(a, 'KNOWS', c) s = ab | ac graph = Graph(auth=('neo4j', "123456")) graph.create(s) aa = graph.nodes.match("Person").first() aa['age'] = 21 graph.push(aa) ''' Object 与 Node 映射 ''' class Person(GraphObject): __primarykey__ = 'name' name = Property() age = Property() location = Property() pp = Person.match(graph).where(age=21).first() print("pp = %s, pp.name = %s, pp.age = %d" % (pp, pp.name, pp.age)) # pp = , pp.name = Carol, pp.age = 21 ''' 使用 Object 更新数据 ''' pp.__ogm__.node # Out[5]: (_114:Person {age: 21, name: 'Carol'}) pp.age = 22 pp.location="Qing Dao" pp.__ogm__.node # Out[7]: (_114:Person {age: 22, location: 'Qing Dao', name: 'Carol'}) graph.push(pp) graph.nodes.match("Person").first() # Out[9]: (_114:Person {age: 22, location: 'Qing Dao', name: 'Carol'}) RelatedTo / RelatedFrom / Related 查看 / 设置 outgoing / incoming / no-direction 关系from py2neo.ogm import RelatedTo class Person(GraphObject): __primarykey__ = 'name' name = Property() age = Property() location = Property() knows = RelatedTo('Person', 'KNOWS') pp = Person.match(graph).where(age=22).first() list(pp.knows) # Out[26]: [] ''' add 创建新的 RelatedTo ''' new_person = Person() new_person.name = "James" new_person.age = 28 new_person.location = "Qing Dao" new_person.knows.add(pp) pp.knows.add(new_person) list(pp.knows) # Out[28]: [, ] ''' 此时只是 Object 更新了,需要同步到数据库 ''' # 更新关系会同时更新新加的节点 graph.push(pp) graph.nodes.match("Person").first() # Out[32]: (_78:Person {age: 28, location: 'Qing Dao', name: 'James'}) graph.push(new_person) ''' remove 删除 RelatedTo ''' pp.knows.remove(new_person) list(pp.knows) # Out[36]: [] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qckNWgqJ-1678944724463)(images/neo4j_py2neo_ogm.jpg)]GraphObject 其他操作方法 pull 根据数据库中的数据更新 GraphObject 中的数据push 更新数据库中的数据delete 删除数据库中的节点 Cypher cypher_escape cypher 转义,将字符串中的特殊字符转义成 cypher 需要的格式from py2neo.cypher import cypher_escape cypher_escape("simple_identifier") # Out[270]: 'simple_identifier' cypher_escape("identifier with spaces") # Out[271]: "'identifier with spaces'" cypher_escape("identifier with `backticks`") # Out[272]: "'identifier with `backticks`'" "MATCH (a:{label}) RETURN id(a)".format(label=cypher_escape("Employee of the Month")) # Out[273]: "MATCH (a:'Employee of the Month') RETURN id(a)" CypherLexer 用于解析 cypher 命令,基于 Pygments lexer frameworkfrom py2neo.cypher.lexer import CypherLexer list(lexer.get_tokens("MATCH (a:Person)-[:KNOWS]->(b) RETURN a")) # Out[290]: # [(Token.Keyword, 'MATCH'), # (Token.Text.Whitespace, ' '), # (Token.Punctuation, '('), # (Token.Name.Variable, 'a'), # (Token.Punctuation, ':'), # (Token.Name.Label, 'Person'), # (Token.Punctuation, ')-['), # (Token.Punctuation, ':'), # (Token.Name.Label, 'KNOWS'), # (Token.Punctuation, ']->('), # (Token.Name.Variable, 'b'), # (Token.Punctuation, ')'), # (Token.Text.Whitespace, ' '), # (Token.Keyword, 'RETURN'), # (Token.Text.Whitespace, ' '), # (Token.Name.Variable, 'a'), # (Token.Text.Whitespace, '\n')] list(lexer.get_statements("CREATE (:Person {name:'Alice'}); MATCH (a:Person {name:'Alice'}) RETURN id(a)")) # Out[291]: # ["CREATE (:Person {name:'Alice'})", # "MATCH (a:Person {name:'Alice'}) RETURN id(a)"]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3