py2neo 创建关系_Neo4j简介及Py2Neo的用法

本文详细介绍了Neo4j图形数据库的Java核心概念、数据结构(节点、边和属性)、查询语言CQL、Py2Neo Python接口的使用方法,包括安装、Node和Relationship操作、Subgraph和Walkable、Graph API及OGM对象图映射。
摘要由CSDN通过智能技术生成

Neo4j是一个世界领先的开源图形数据库,由 Java 编写。图形数据库也就意味着它的数据并非保存在表或集合中,而是保存为节点以及节点之间的关系。 Neo4j 的数据由下面几部分构成:

节点

属性

Neo4j 除了顶点(Node)和边(Relationship),还有一种重要的部分——属性。无论是顶点还是边,都可以有任意多的属性。属性的存放类似于一个 HashMap,Key 为一个字符串,而 Value 必须是基本类型或者是基本类型数组。 在Neo4j中,节点以及边都能够包含保存值的属性,此外:

可以为节点设置零或多个标签(例如 Author 或 Book)

每个关系都对应一种类型(例如 WROTE 或 FRIEND_OF)

关系总是从一个节点指向另一个节点(但可以在不考虑指向性的情况下进行查询)

Neo4j的特点

它拥有简单的查询语言 Neo4j CQL

它遵循属性图数据模型

它通过使用 Apache Lucence 支持索引

它支持 UNIQUE 约束

它包含一个用于执行 CQL 命令的 UI:Neo4j 数据浏览器

它支持完整的 ACID(原子性,一致性,隔离性和持久性)规则

它采用原生图形库与本地 GPE(图形处理引擎)

它支持查询的数据导出到 Json 和 XLS 格式

它提供了 REST API,可以被任何编程语言(如 Java,Spring,Scala 等)访问

它提供了可以通过任何 UI MVC 框架(如 Node JS )访问的 Java 脚本

它支持两种 Java API:Cypher API 和 Native Java API 来开发 Java 应用程序

Neo4j安装

Neo4j CQL命令

Py2Neo用法

Py2Neo 是用来对接 Neo4j 的 Python 库,接下来对其详细介绍。

相关链接

安装方法

使用 Pip 安装即可:

1

pip3 install py2neo

Node & Relationship

Neo4j 里面最重要的两个数据结构就是节点和关系,即 Node 和 Relationship,可以通过 Node 或 Relationship 对象创建,实例如下:

1

2

3

4

5

6

from py2neo import Node, Relationship

a = Node('Person', name='Alice')

b = Node('Person', name='Bob')

r = Relationship(a, 'KNOWS', b)

print(a, b, r)

运行结果:

1

(alice:Person {name:"Alice"}) (bob:Person {name:"Bob"}) (alice)-[:KNOWS]->(bob)

这样我们就成功创建了两个 Node 和两个 Node 之间的 Relationship。 Node 和 Relationship 都继承了 PropertyDict 类,它可以赋值很多属性,类似于字典的形式,例如可以通过如下方式对 Node 或 Relationship 进行属性赋值,接着上面的代码,实例如下:

1

2

3

4

a['age'] = 20

b['age'] = 21

r['time'] = '2017/08/31'

print(a, b, r)

运行结果:

1

(alice:Person {age:20,name:"Alice"}) (bob:Person {age:21,name:"Bob"}) (alice)-[:KNOWS {time:"2017/08/31"}]->(bob)

可见通过类似字典的操作方法就可以成功实现属性赋值。 另外还可以通过 setdefault() 方法赋值默认属性,例如:

1

2

a.setdefault('location', '北京')

print(a)

运行结果:

1

(alice:Person {age:20,location:"北京",name:"Alice"})

可见没有给 a 对象赋值 location 属性,现在就会使用默认属性。 但如果赋值了 location 属性,则它会覆盖默认属性,例如:

1

2

3

a['location'] = '上海'

a.setdefault('location', '北京')

print(a)

运行结果:

1

(alice:Person {age:20,location:"上海",name:"Alice"})

另外也可以使用 update() 方法对属性批量更新,接着上面的例子实例如下:

1

2

3

4

5

6

data = {

'name': 'Amy',

'age': 21

}

a.update(data)

print(a)

运行结果:

1

(alice:Person {age:21,location:"上海",name:"Amy"})

可以看到这里更新了 a 对象的 name 和 age 属性,没有更新 location 属性,则 name 和 age 属性会更新,location 属性则会保留。

Subgraph

Subgraph,子图,是 Node 和 Relationship 的集合,最简单的构造子图的方式是通过关系运算符,实例如下:

1

2

3

4

5

6

7

from py2neo import Node, Relationship

a = Node('Person', name='Alice')

b = Node('Person', name='Bob')

r = Relationship(a, 'KNOWS', b)

s = a | b | r

print(s)

运行结果:

1

({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})}, {(alice)-[:KNOWS]->(bob)})

这样就组成了一个 Subgraph。 另外还可以通过 nodes() 和 relationships() 方法获取所有的 Node 和 Relationship,实例如下:

1

2

print(s.nodes())

print(s.relationships())

运行结果:

1

2

frozenset({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})})

frozenset({(alice)-[:KNOWS]->(bob)})

可以看到结果是 frozenset 类型。 另外还可以利用 & 取 Subgraph 的交集,例如:

1

2

3

s1 = a | b | r

s2 = a | b

print(s1 & s2)

运行结果:

1

({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})}, {})

可以看到结果是二者的交集。 另外我们还可以分别利用 keys()、labels()、nodes()、relationships()、types() 分别获取 Subgraph 的 Key、Label、Node、Relationship、Relationship Type,实例如下:

1

2

3

4

5

6

s = a | b | r

print(s.keys())

print(s.labels())

print(s.nodes())

print(s.relationships())

print(s.types())

运行结果:

1

2

3

4

5

frozenset({'name'})

frozenset({'Person'})

frozenset({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})})

frozenset({(alice)-[:KNOWS]->(bob)})

frozenset({'KNOWS'})

另外还可以用 order() 或 size() 方法来获取 Subgraph 的 Node 数量和 Relationship 数量,实例如下:

1

2

3

4

from py2neo import Node, Relationship, size, order

s = a | b | r

print(order(s))

print(size(s))

运行结果:

1

2

2

1

Walkable

Walkable 是增加了遍历信息的 Subgraph,我们通过 + 号便可以构建一个 Walkable 对象,例如:

1

2

3

4

5

6

7

8

9

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(w)

运行结果:

1

(alice)-[:KNOWS]->(bob)-[:LIKES]->(mike)

这样我们就形成了一个 Walkable 对象。 另外我们可以调用 walk() 方法实现遍历,实例如下:

1

2

3

4

from py2neo import walk

for item in walk(w):

print(item)

运行结果:

1

2

3

4

5

6

7

(alice:Person {name:"Alice"})

(alice)-[:KNOWS]->(bob)

(bob:Person {name:"Bob"})

(bob)-[:LIKES]->(mike)

(mike:Person {name:"Mike"})

(alice)-[:KNOWS]->(mike)

(alice:Person {name:"Alice"})

可以看到它从 a 这个 Node 开始遍历,然后到 b,再到 c,最后重新回到 a。 另外还可以利用 start_node()、end_node()、nodes()、relationships() 方法来获取起始 Node、终止 Node、所有 Node 和 Relationship,例如:

1

2

3

4

print(w.start_node())

print(w.end_node())

print(w.nodes())

print(w.relationships())

运行结果:

1

2

3

4

(alice:Person {name:"Alice"})

(alice:Person {name:"Alice"})

((alice:Person {name:"Alice"}), (bob:Person {name:"Bob"}), (mike:Person {name:"Mike"}), (alice:Person {name:"Alice"}))

((alice)-[:KNOWS]->(bob), (bob)-[:LIKES]->(mike), (alice)-[:KNOWS]->(mike))

可以看到本例中起始和终止 Node 都是同一个,这和 walk() 方法得到的结果是一致的。

Graph

在 database 模块中包含了和 Neo4j 数据交互的 API,最重要的当属 Graph,它代表了 Neo4j 的图数据库,同时 Graph 也提供了许多方法来操作 Neo4j 数据库。 Graph 在初始化的时候需要传入连接的 URI,初始化参数有 bolt、secure、host、http_port、https_port、bolt_port、user、password,详情说明可以参考:http://py2neo.org/v3/database.html#py2neo.database.Graph。 初始化的实例如下:

1

2

3

4

from py2neo import Graph

graph_1 = Graph()

graph_2 = Graph(host="localhost")

graph_3 = Graph("http://localhost:7474/db/data/")

另外我们还可以利用 create() 方法传入 Subgraph 对象来将关系图添加到数据库中,实例如下:

1

2

3

4

5

6

7

8

from py2neo import Node, Relationship, Graph

a = Node('Person', name='Alice')

b = Node('Person', name='Bob')

r = Relationship(a, 'KNOWS', b)

s = a | b | r

graph = Graph(password='123456')

graph.create(s)

这里必须确保 Neo4j 正常运行,其密码为 123456,这里调用 create() 方法即可完成图的创建,结果如下:

另外我们也可以单独添加单个 Node 或 Relationship,实例如下:

1

2

3

4

5

6

7

8

from py2neo import Graph, Node, Relationship

graph = Graph(password='123456')

a = Node('Person', name='Alice')

graph.create(a)

b = Node('Person', name='Bob')

ab = Relationship(a, 'KNOWS', b)

graph.create(ab)

运行结果如下:

另外还可以利用 data() 方法来获取查询结果:

1

2

3

4

5

from py2neo import Graph

graph = Graph(password='123456')

data = graph.data('MATCH (p:Person) return p')

print(data)

运行结果:

1

[{'p': (e0d0f96:Person {name:"Alice"})}, {'p': (cfe57d0:Person {name:"Bob"})}]

这里是通过 CQL 语句实现的查询,输出结果即 CQL 语句的返回结果,是列表形式。 另外输出结果还可以直接转化为 DataFrame 对象,实例如下:

1

2

3

4

5

6

from py2neo import Graph

from pandas import DataFrame

graph = Graph(password='123456')

data = graph.data('MATCH (p:Person) return p')

df = DataFrame(data)

print(df)

运行结果:

1

2

3

p

0 {'name': 'Alice'}

1 {'name': 'Bob'}

另外可以使用 find_one() 或 find() 方法进行 Node 的查找,可以利用 match() 或 match_one() 方法对 Relationship 进行查找:

1

2

3

4

5

6

7

from py2neo import Graph

graph = Graph(password='123456')

node = graph.find_one(label='Person')

print(node)

relationship = graph.match_one(rel_type='KNOWS')

print(relationship)

运行结果:

1

2

(c7402c7:Person {age:21,name:"Alice"})

(c7402c7)-[:KNOWS]->(e2c42fc)

如果想要更新 Node 的某个属性可以使用 push() 方法,例如:

1

2

3

4

5

6

7

8

from py2neo import Graph, Node

graph = Graph(password='123456')

a = Node('Person', name='Alice')

node = graph.find_one(label='Person')

node['age'] = 21

graph.push(node)

print(graph.find_one(label='Person'))

运行结果:

1

(a90a763:Person {age:21,name:"Alice"})

如果想要删除某个 Node 可以使用 delete() 方法,例如:

1

2

3

4

5

6

7

from py2neo import Graph

graph = Graph(password='123456')

node = graph.find_one(label='Person')

relationship = graph.match_one(rel_type='KNOWS')

graph.delete(relationship)

graph.delete(node)

在删除 Node 时必须先删除其对应的 Relationship,否则无法删除 Node。 另外我们也可以通过 run() 方法直接执行 CQL 语句,例如:

1

2

3

4

5

from py2neo import Graph

graph = Graph(password='123456')

data = graph.run('MATCH (p:Person) RETURN p LIMIT 5')

print(list(data))

运行结果:

1

[('p': (b6f61ff:Person {age:20,name:"Alice"})), ('p': (cc238b1:Person {age:20,name:"Alice"})), ('p': (b09e672:Person {age:20,name:"Alice"}))]

NodeSelector

Graph 有时候用起来不太方便,比如如果要根据多个条件进行 Node 的查询是做不到的,在这里更方便的查询方法是利用 NodeSelector,我们首先新建如下的 Node 和 Relationship,实例如下:

1

2

3

4

5

6

7

8

9

10

11

from py2neo import Graph, Node, Relationship

graph = Graph(password='123456')

a = Node('Person', name='Alice', age=21, location='广州')

b = Node('Person', name='Bob', age=22, location='上海')

c = Node('Person', name='Mike', age=21, location='北京')

r1 = Relationship(a, 'KNOWS', b)

r2 = Relationship(b, 'KNOWS', c)

graph.create(a)

graph.create(r1)

graph.create(r2)

运行结果:

在这里我们用 NodeSelector 来筛选 age 为 21 的 Person Node,实例如下:

1

2

3

4

5

6

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')

selector = NodeSelector(graph)

persons = selector.select('Person', age=21)

print(list(persons))

运行结果:

1

[(d195b2e:Person {age:21,location:"广州",name:"Alice"}), (eefe475:Person {age:21,location:"北京",name:"Mike"})]

另外也可以使用 where() 进行更复杂的查询,例如查找 name 是 A 开头的 Person Node,实例如下:

1

2

3

4

5

6

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')

selector = NodeSelector(graph)

persons = selector.select('Person').where('_.name =~ "A.*"')

print(list(persons))

运行结果:

1

[(bcd8072:Person {age:21,location:"广州",name:"Alice"})]

在这里用了正则表达式匹配查询。 另外也可以使用 order_by() 进行排序:

1

2

3

4

5

6

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')

selector = NodeSelector(graph)

persons = selector.select('Person').order_by('_.age')

print(list(persons))

运行结果:

1

[(e3fc3d7:Person {age:21,location:"广州",name:"Alice"}), (da0179d:Person {age:21,location:"北京",name:"Mike"}), (cafa16e:Person {age:22,location:"上海",name:"Bob"})]

前面返回的都是列表,如果要查询单个节点的话,可以使用 first() 方法,实例如下:

1

2

3

4

5

6

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')

selector = NodeSelector(graph)

person = selector.select('Person').where('_.name =~ "A.*"').first()

print(person)

运行结果:

1

(ea81c04:Person {age:21,location:"广州",name:"Alice"})

OGM

OGM 类似于 ORM,意为 Object Graph Mapping,这样可以实现一个对象和 Node 的关联,例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

from py2neo.ogm import GraphObject, Property, RelatedTo, RelatedFrom

class Movie(GraphObject):

__primarykey__ = 'title'

title = Property()

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')

我们可以用它来结合 Graph 查询,例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

from py2neo import Graph

from py2neo.ogm import GraphObject, Property

graph = Graph(password='123456')

class Person(GraphObject):

__primarykey__ = 'name'

name = Property()

age = Property()

location = Property()

person = Person.select(graph).where(age=21).first()

print(person)

print(person.name)

print(person.age)

运行结果:

1

2

3

Alice

21

这样我们就成功实现了对象和 Node 的映射。 我们可以用它动态改变 Node 的属性,例如修改某个 Node 的 age 属性,实例如下:

1

2

3

4

5

person = Person.select(graph).where(age=21).first()

print(person.__ogm__.node)

person.age = 22

print(person.__ogm__.node)

graph.push(person)

运行结果:

1

2

(ccf5640:Person {age:21,location:"北京",name:"Mike"})

(ccf5640:Person {age:22,location:"北京",name:"Mike"})

另外我们也可以通过映射关系进行 Relationship 的调整,例如通过 Relationship 添加一个关联 Node,实例如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

from py2neo import Graph

from py2neo.ogm import GraphObject, Property, RelatedTo

graph = Graph(password='123456')

class Person(GraphObject):

__primarykey__ = 'name'

name = Property()

age = Property()

location = Property()

knows = RelatedTo('Person', 'KNOWS')

person = Person.select(graph).where(age=21).first()

print(list(person.knows))

new_person = Person()

new_person.name = 'Durant'

new_person.age = 28

person.knows.add(new_person)

print(list(person.knows))

运行结果:

1

2

[]

[, ]

这样我们就完成了 Node 和 Relationship 的添加,同时由于设置了 primarykey 为 name,所以不会重复添加。 但是注意此时数据库并没有更新,只是对象更新了,如果要更新到数据库中还需要调用 Graph 对象的 push() 或 pull() 方法,添加如下代码即可:

1

graph.push(person)

也可以通过 remove() 方法移除某个关联 Node,实例如下:

1

2

3

4

5

person = Person.select(graph).where(name='Alice').first()

target = Person.select(graph).where(name='Durant').first()

person.knows.remove(target)

graph.push(person)

graph.delete(target)

这里 target 是 name 为 Durant 的 Node,代码运行完毕后即可删除关联 Relationship 和删除 Node。 以上便是 OGM 的用法,查询修改非常方便,推荐使用此方法进行 Node 和 Relationship 的修改。 更多内容可以查看:http://py2neo.org/v3/ogm.html#module-py2neo.ogm。

结语

以上便是对 Neo4j 的相关介绍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值