当前位置: 首页 > 工具软件 > Py++ > 使用案例 >

Py2neo的基本用法

诸葛利
2023-12-01

neo4j目前是图数据库的主流,neo4j的Cypher语法简单直观,但是不便于流程化。如果习惯在python环境下处理数据,那么还是要用到python的neo4j库,即py2neo.

py2neo本身并不复杂,但要先适应它的思考模式。另一个问题是py2neo文档的示例较少,而且不同版本的py2neo挺不相同,容易弄混。这里要讲的是目前的v4版本。

连接数据库和图

from py2neo import *           # *中常用的是Node,Relationship,Graph
graph = Graph(url,username='name',password='pw')

2.查看数据库的基本属性

graph.schema.node_labels       # 查看图结构中节点标签的类别,返回结果是一个frozenset
 graph.schema.relationship_types   # 查看图结构中关系的类型

3.数据操作

数据操作分为两种方式,一种是直接传入cypher语句,这里我们称之为cypher外壳;另一种是采用py2neo自己的数据结构和编写方式,我们称为py2neo方法。

在讲这两种方式之前,先提一下通用的pull()、push()等操作。

因为常需要从服务器端取数据,同时编写程序时本地也会产生Node,Relationship等数据,因此需要二者的版本协同。常规的处理方法如下:

graph = Graph()
tx  = graph.begin()          # 开始一个Transaction
node_1 = Node("Person",name="Peter")
tx.create(node_1)           
tx.push(node_1)              # push到服务器
#or 
tx.commit()             # 将以上更改一次提交

3.1 cypher外壳

这种方法的基本用法是graph.run(‘a cypher expression’),如

result =graph.run('match (p:Paper) return p.title,p.author limit 20')

适合更熟悉Cypher语法的同学使用,需要注意的是,运行graph.run()返回的结果是一个cursor对象。cursor相当于结果的一个游标(a cursor is a navigator for a stream of records).可以通过循环调用。

while cursor.forward():
    print(cursor.current['name'])
# or
for record in cursor:
    print(record["name"])

此外graph.run()的结果可以通过数据形式呈现。数据基本格式是list of dictionary,可以按需求转换为其它格式:

graph.run().data()               # a list of dictionary
graph.run().to_data_frame()      # pd.DataFrame
graph.run().to_ndarray()         # numpy.ndarray
graph.run().to_subgraph()
graph.run().to_table()

3.2 py2neo方法

py2neo方法即前面的graph类中的函数。neo4j的主要功能是图数据的存储和查询,相应的py2neo方法也可以从这两方面来考察。

(1)存储

除了前面的创建节点,还有创建关系以及子图。

a = Node("Person",name="Alice")
b = Node("Person",name="Bob")
r = Relationship(a,"KNOWS",b)
s = a|b|r
graph = Graph()
graph.create(s)

创建节点可以采用merge方法,需要注意的是py2neo和cypher中的merge方法有所不同。

在cypher中,MERGE方式是当你创建一个实体时,程序会检测是否已有这个实体存在,检测的方法是进行label和property的匹配。如果已存在则不创建。 py2neo方法中的merge则是,同样进行匹配,如果匹配上则用当前实体覆盖数据库中的已有实体。 这里的主要区别在于,匹配时一般只会用到关键的少数property,根据某个property去决定是否覆盖时,其他property可能是不相等的。

因此cypher是用数据库实体覆盖新创建的,py2neo是用新的覆盖旧的。 考虑到创建时属性可能比较少,因此在py2neo中慎用merge,可以先做存在判断,然后再用create语句.

具体的,merge语句的使用方式为:

graph.merge(node_1,"Person","name")       # 根据name属性对person结点进行merge

相应的cypher语句中的merge为:

match (c:course)
merge (t:teacher {name:c.teacher})
return c.name,c.teacher

(2)查询

py2neo提供了专门的查询模块,即NodeMatcher和RelationshipMatcher,使用格式为

matcher_1 = NodeMatcher(graph)
matcher_2 = RelationshipMatcher(graph)
node = matcher_1.match("Paper",ID='09076').where(year=2017)  # 匹配指定ID和year的Paper结点
relation = matcher_2.matcher(r_type="Cited").limit(50)

注意使用这两个模块后返回的结果仍然是NodeMatcher对象或RelationshipMatcher对象,要将其转换为实体,可以采用first()函数,或者变换成列表。

node_1 = matcher_1.match("Paper",ID='09076').first()    # 取第一个匹配到的节点
result_1 = list(node)           # 转换为列表
result_2 = list(result)

此外,node和relationship数据类型也自带匹配属性,如

graph.node.matcher("Person").first()

但是这样匹配的效率似乎比较低,运行更慢。

以上py2neo的匹配,其缺点在于匹配被人为分割成节点和关系的匹配,使用起来不灵活,因为节点和关系的匹配常常是紧密联系的。相比之下,cypher的原生匹配就很灵活,没有限定类型。

match g = (p1:Person) -[r:]->(p2:Paper)
where p2.year>2008
return g,p1.name,r.type,p2.title

3.3 py2neo.ogm

py2neo中的ogm模块是Object-Graph Mapping的简写,这里将它和普通py2neo方法分开单独讲,ogm是基于Graphobject的。

一个Graphobject的实例可以包含节点、标签或相关对象等内容。

class Movie(GraphObject):
    __primarylabel__ = 'Movie'
    __primarykey__ = 'title'
    
   title = Property()              # 影片名
   tag_line = Property('tagline')  
   release = Property()            # 发行时间
   restricted = Lable()            # 是否限制级
   
   actors = RelatedFrom("Person","ACTED_IN")
   directors = RelatedFrom("Person","DIRECTED")
   producers = RelatedFrom("Person","PRODUCED")

class Person(GraphObject):
    __primarykey__ = "name"

    name = Property()       
    acted_in = RelatedTo(Movie)

Property是属性,通过语句如release = Property()指定release为属性,接着就可以赋值

M = Movie()
M.release = 1995

Label是标签,用法同Property,但Label是binary变量。

RelationTo和RelatedFrom指定了关系管理的实体和关系的方向。

graphObject对象自身也可以进行查询操作,如Person.match(graph,“Alice”).first()

如前文所说,效率可能没有NodeMatcher方法高。

  1. 小结

以上就是笔者整理的py2neo基本使用方法,作为一个小工具,py2neo内容本身不多,但是限于篇幅,还有一些有用的内容没有涉及到。例如为实体添加特定约束等,有机会再写。

 类似资料: