py2neo操作グラフデータベースneo4j

1.コンセプト

グラフ:データ構造のグラフは、ノードとノード間のエッジで構成されます。ノードはエンティティを表し、エッジはエンティティ間の接続を表します。

グラフデータベース:管理データをグラフ構造で格納するデータベース。一部のデータベースは、最適化後にネイティブグラフ構造、つまりネイティブグラフストレージを直接格納します。一部のグラフデータベースは、グラフデータをシリアル化し、リレーショナルデータベースまたは他のデータベースに格納します。

グラフデータベースを使用してデータを格納する理由は、エンティティ間の複雑な関係を持つデータの処理に大きな利点があるためです。データ間の関係を処理する場合、従来のリレーショナルデータベースを使用するのは実際には不便です。たとえば、コースを受講する学生をクエリする場合、2つのテーブルを結合し、コースを受講する学生がどのコースを受講するかをクエリする必要があります。これには2つの結合操作が必要です。非常に複雑な関係と大量のデータが関係する場合、関係タイプデータベースの効率が非常に低い。グラフストレージを使用すると、ノード間のエッジを介して結果を簡単にクエリできます。

ダイアグラムモデル:

ノード(ノード)は、エンティティを表す主要なデータ要素です。

プロパティ(プロパティ)はエンティティの特性を説明するために使用され、キーと値のペアの形式で表されます。キーは文字列です。プロパティにインデックスと制約を作成できます。

関係(関係)は、エンティティ間の関係を表します。関係には方向があります。エンティティ間には複数の関係があり、関係には属性を持つこともできます。

ラベル(Label)はエンティティを分類するために使用されます。エンティティには複数のラベルを付けることができ、ラベルにインデックスを付けると検索を高速化できます

2、Neo4j

Neo4jは現在最も人気のあるグラフデータベースです。ネイティブのグラフストレージを使用し、それをWindowsにダウンロードしてインストールし、次のアドレスhttps://neo4j.com/download/community-edition/にアクセスしますLinuxでは、次のコマンドでダウンロードして解凍します。

curl -O http://dist.neo4j.org/neo4j-community-3.4.5-unix.tar.gz
tar -axvf neo4j-community-3.4.5-unix.tar.gz

構成ファイルconf / neo4j.confを変更します

# 修改第22行load csv时l路径,在前面加个#,可从任意路径读取文件
#dbms.directories.import=import

# 修改35行和36行,设置JVM初始堆内存和JVM最大堆内存
# 生产环境给的JVM最大堆内存越大越好,但是要小于机器的物理内存
dbms.memory.heap.initial_size=5g
dbms.memory.heap.max_size=10g

# 修改46行,可以认为这个是缓存,如果机器配置高,这个越大越好
dbms.memory.pagecache.size=10g

# 修改54行,去掉改行的#,可以远程通过ip访问neo4j数据库
dbms.connectors.default_listen_address=0.0.0.0

# 默认 bolt端口是7687,http端口是7474,https关口是7473,不修改下面3项也可以
# 修改71行,去掉#,设置http端口为7687,端口可以自定义,只要不和其他端口冲突就行
#dbms.connector.bolt.listen_address=:7687

# 修改75行,去掉#,设置http端口为7474,端口可以自定义,只要不和其他端口冲突就行
dbms.connector.http.listen_address=:7474

# 修改79行,去掉#,设置http端口为7473,端口可以自定义,只要不和其他端口冲突就行
dbms.connector.https.listen_address=:7473

# 去掉#,允许从远程url来load csv
dbms.security.allow_csv_import_from_file_urls=true

# 修改250行,去掉#,设置neo4j-shell端口,端口可以自定义,只要不和其他端口冲突就行
dbms.shell.port=1337

# 修改254行,设置neo4j可读可写
dbms.read_only=false

実行は、ブラウザでサービスを開始し、binディレクトリに起動./neo4j ます。http://サーバのIPアドレス:7474 /ブラウザ/のNeo4jビジュアルインターフェースを見ることができます

3、py2neo

py2neoは、コミュニティのサードパーティライブラリであり、これを使用して、Pythonをより簡単に使用してneo4jを操作できます。

py2neoをインストールします。pipinstall py2neo、インストールしたバージョンは4.3.0です。

3.1、Node与Relationship

ノードとノード間の関係を作成します。次のpy2neo関連クラスを使用する前にインポートする必要があることに注意してください:

# 引入库
from py2neo import Node, Relationship
# 创建节点a、b并定义其标签为Person,属性name
a = Node("Person", name="Alice",height=166)
b = Node("Person", name="Bob")
# 节点添加标签
a.add_label('Female')
# 创建ab之间的关系
ab = Relationship(a, "KNOWS", b)
# 输出节点之间的关系:(Alice)-[:KNOWS]->(Bob)
print(ab)

ノードとリレーションシップはどちらも、Pythonのディクショナリに似たPropertyDictクラスを継承します。ノードまたはリレーションシップのプロパティは、次の方法で割り当ててアクセスできます。

# 节点和关系添加、修改属性
a['age']=20
ab['time']='2019/09/03'
# 删除属性
del a['age']
# 打印属性
print(a[name])
# 设置默认属性,如果没有赋值,使用默认值,否则设置的新值覆盖默认值
a.setdefault('sex','unknown')
# 更新属性
a.update(age=22, sex='female')
ab.update(time='2019/09/03')

3.2、サブグラフ

ノードと関係で構成されるセットはサブグラフであり、交差演算子&、ユニオン|、差分セット、対称差分セットは、関係演算子^によって取得されます。

subgraph.labelsはサブグラフのすべてのラベルセットを返し、keys()はすべての属性セットを返し、nodesはすべてのノードセットを返し、relationshipsはすべての関係セットを返します

# 构建一个子图
s = a | b | ab
# 对图中的所有节点集合进行遍历
for item in s.nodes:
    print('s的节点:', item)

通常、グラフ内のすべてのノードと関係はサブグラフを形成し、それらを均一にデータベースに書き込みます。これは、単一のノードに複数回書き込むよりも効率的です

# 连接neo4j数据库,输入地址、用户名、密码
graph = Graph('http://localhost:7474', username='neo4j', password='123456')
# 将节点和关系通过关系运算符合并为一个子图,再写入数据库
s=a | b | ab
graph.create(s)

3.3、歩きやすい

Walkableは、サブグラフサブグラフに基づいてトラバーサル情報を追加するオブジェクトで、これを介してグラフデータベースを簡単にトラバースできます。

+記号を介して関係を接続し、ウォーク可能なオブジェクトを形成します。walk()関数をウォークスルーすると、start_node、end_node、nodes、relationshipプロパティを使用して、開始ノード、終了ノード、すべてのノード、および関係を取得できます

# 组合成一个walkable对象w
w = ab + bc + ac
# 对w进行遍历
for item in walk(w):
    print(item)

# 访问w的初始、终止节点
print('起始节点:', w.start_node, ' 终止节点:', w.end_node)
# 访问w的所有节点、关系列表
print('节点列表:', w.nodes)
print('关系列表:', w.relationships)

実行結果は次のとおりです。

(:Person {age: 20, name: 'Bob'})
(Bob)-[:KNOWS {}]->(Alice)
(:Person {age: 21, name: 'Alice'})
(Alice)-[:LIKES {}]->(Mike)
(:Person {name: 'Mike'})
(Bob)-[:KNOWS {}]->(Mike)
(:Person {age: 20, name: 'Bob'})
起始节点: (:Person {age: 22, name: 'Bob', sex: 'female'})  终止节点: (:Person {age: 22, name: 'Bob', sex: 'female'})
节点列表: ((:Person {age: 22, name: 'Bob', sex: 'female'}), (:Person {age: 21, name: 'Alice'}), (:Person {name: 'Mike'}), (:Person {age: 22, name: 'Bob', sex: 'female'}))
关系列表: ((Bob)-[:KNOWS {time: '2019/09/03'}]->(Alice), (Alice)-[:LIKES {}]->(Mike), (Bob)-[:KNOWS {}]->(Mike))

3.4、グラフ

py2neoは、グラフオブジェクトを介してneo4jデータベースを操作します。現在のneo4jは、グラフを定義するために1つのデータベースのみをサポートします

グラフの初期化関数を介してデータベースへの接続を完了し、グラフオブジェクトを作成します。

graph.create()は、サブグラフをデータベースに書き込むか、一度に1つのノードまたは関係のみを書き込むことができます

graph.delete()は指定されたサブグラフを削除し、graph.delete_all()はすべてのサブグラフを削除します

graph.seperate()は指定された関係を削除します

# 初始化连接neo4j数据库,参数依次为url、用户名、密码
graph = Graph('http://localhost:7474', username='neo4j', password='123456')
# 写入子图w
graph.create(w)
# 删除子图w
graph.delete(w)
# 删除所有图
graph.delete_all()
# 删除关系rel
graph.separate(rel)

graph.match(ノード=なしr_type =なし制限=なし)は、条件を満たす関係を検索します。最初のパラメーターはノードセットまたはセット(開始ノード、終了ノード)です。省略した場合、すべてのノードを表します。2番目のパラメーターは関係の属性で、3番目のパラメーターは返される結果の数です。代わりにmatch_one()を使用して結果を返すこともできます。たとえば、ノードaが知っているすべての人を検索します。

# 查找所有以a为起点,并且属性为KNOWS的关系
res = graph.match((a, ), r_type="KNOWS")
# 打印关系的终止节点,即为a所有认识的人
for rel in res:
    print(rel.end_node["name"])

指定されたノードを見つけるには、graph.nodes.match()を使用します。最初の()、where()、order_by()およびその他の関数を使用して、検索に対して高度な制限を行うことができます

ノードまたは関係のIDで検索することもできます

# 查找标签为Person,属性name="Alice"的节点,并返回第一个结果
graph.nodes.match("Person", name="Alice").first()

# 查找所有标签为Person,name以B开头的节点,并将结果按照age字段排序
res = graph.nodes.match("Person").where("_.name =~ 'B.*'").order_by('_.age')
for node in res:
    print(node['name'])

# 查找id为4的节点
t_node = graph.nodes[4]
# 查找id为196的关系
rel = graph.relationships[196]

Graphオブジェクトを介してCypher操作を実行し、返された結果を処理する

graph.evaluate()は、Cypherステートメントを実行し、結果の最初のデータを返します

# 执行Cypher语句并返回结果集的第一条数据
res = graph.evaluate('MATCH (p:Person) return p')
# 输出:(_3:Person {age: 20, name: 'Bob'})
print(res)

graph.run()は、Cypherステートメントを実行し結果データストリームのカーソルCursorを返します。forward()メソッドは、カーソルを継続的に前方に移動して、結果セットの各レコードオブジェクトを切り替えます。

# 查询(p1)-[k]->(p2),并返回所有节点和关系
gql="MATCH (p1:Person)-[k:KNOWS]->(p2:Person) RETURN *"
cursor=graph.run(gql)
# 循环向前移动游标
while cursor.forward():
    # 获取并打印当前的结果集
    record=cursor.current
    print(record)

 印刷された各Recordレコードオブジェクトを以下に示します。その中の要素がkey = valueのセットであることがわかります。get(key)メソッドを使用して、特定の要素を取得できます。メソッド項目(キー)を通じて、レコードで指定されたキーを(キー、値)タプルの形式で返すことができます

<Record k=(xiaowang)-[:KNOWS {}]->(xiaozhang) p1=(_96:Person {name: 'xiaowang'}) p2=(_97:Person {name: 'xiaozhang'})>
    record = cursor.current
    print('通过get返回:', record.get('k'))
    for (key, value) in record.items('p1', 'p2'):
        print('通过items返回元组:', key, ':', value)

# 运行结果如下
'''
通过get返回: (xiaowang)-[:KNOWS {}]->(xiaozhang)
通过items返回元组: p1 : (_92:Person {name: 'xiaowang'})
通过items返回元组: p2 : (_93:Person {name: 'xiaozhang'})
'''

graph.run()によって返された結果をdata()メソッドを介して辞書リストに変換することもできます。すべての結果は全体としてリストであり、各結果は辞書の形式です。クエリと結果は次のとおりです。リストと辞書にアクセスできますデータを取得する方法:

# 查询(p1)-[k]->(p2),并返回所有节点和关系
gql = "MATCH (p1:Person)-[k:KNOWS]->(p2:Person) RETURN *"
res = graph.run(gql).data()
print(res)

#结果如下:
'''
[{'k': (xiaowang)-[:KNOWS {}]->(xiaozhang), 
  'p1': (_196:Person {name: 'xiaowang'}), 
  'p2': (_197:Person {name: 'xiaozhang'})}, 
{'k': (xiaozhang)-[:KNOWS {}]->(xiaozhao), 
 'p1': (_197:Person {name: 'xiaozhang'}),
 'p2': (_198:Person {name: 'xiaozhao'})},
{'k': (xiaozhao)-[:KNOWS {}]->(xiaoli),
 'p1': (_198:Person {name: 'xiaozhao'}),
 'p2': (_199:Person {name: 'xiaoli'})}
]
'''

返された結果をgraph.run()を介してSubGraphオブジェクトに変換し、To_subgraph()メソッドを使用して、以前のSubGraphオブジェクトの操作方法に従ってノードオブジェクトを取得します。ここでのノードオブジェクトは、以前のノードに従って直接操作できます。

# 查询(p1)-[k]->(p2),并返回所有节点和关系
gql = "MATCH (p1:Person)-[k:KNOWS]->(p2:Person) RETURN *"
sub_graph = graph.run(gql).to_subgraph()
# 获取子图中所有节点对象并打印
nodes=sub_graph.nodes
for node in nodes:
    print(node)

# 输出的节点对象如下:
'''
(_101:Person {name: 'xiaozhang'})
(_100:Person {name: 'xiaowang'})
(_103:Person {name: 'xiaoli'})
(_102:Person {name: 'xiaozhao'})
'''

3.5、GMO

オブジェクトとグラフのマッピングは、グラフデータベースのノードをPythonオブジェクトにマッピングし、オブジェクトを使用してノードにアクセスして操作します。

図の各ラベルをpythonクラスとして定義します。これはGraphObjectから継承します。使用する前にインポートに注意してください。定義では、データクラスの主キーを指定し、クラスのプロパティ()、ラベル()、関係RelationTo()/ RelatedFromを定義できます。

from py2neo.ogm import GraphObject, Property, RelatedTo, RelatedFrom, Label
class Person(GraphObject):
    # 定义主键
    __primarykey__ = 'name'
    # 定义类的属性
    name=Property()
    age=Property()
    # 定义类的标签
    student=Label()
    # 定义Person指向的关系
    knows=RelatedTo('Person','KNOWS')
    # 定义指向Person的关系
    known=RelatedFrom('Person','KNOWN')

クラスメソッドwrap()は、共通ノードをクラスオブジェクトに変換できます。

クラスメソッドmatch(graph、primary_key)は、主キーの値がprimary_keyであるグラフ内のノードを見つけることができます

クラス構築メソッドを介して直接オブジェクトを作成し、オブジェクトのプロパティとメソッドに直接アクセスし、関係メソッドadd()を介して関係を追加できます。

クラスのラベルはブール値です。デフォルトはFalseで、Trueに変更します。オブジェクトにラベルを追加できます

# 将节点c转化为OGM类型
c=Person.wrap(c)
print(c.name)
# 查找Person类中主键(name)为Alice的节点
ali=Person.match(graph,'Alice').first()
# 创建一个新的Person对象并对其属性赋值
new_person = Person()
new_person.name = 'Durant'
new_person.age = 28
# 标签值默认为False
print(new_person.student)
# 修改bool值为True,为对象添加student标签
new_person.student=True
# 将修改后的图写入数据库
graph.push(ali)

ノードクラスを定義するときに、関連する関係を定義することもできます。たとえば、RelatedTo()およびRelatedFrom()を介してノードからポイントされる関係を定義して、ノードを指す関係を定義できます。add()で関係を追加する、clear()でノードのすべての関係をクリアする、get()で関係属性を取得する、remove()で関係を明確に指定する、update()更新など、オブジェクト呼び出し関係の対応するメソッドを介してノードの周囲の関係操作を完了する関係

class Person(GraphObject):
    # 定义Person指向的关系
    knows=RelatedTo('Person','KNOWS')
    # 定义指向Person的关系
    known=RelatedFrom('Person','KNOWN')

# 新建一个从ali指向new_person的关系
ali.knows.add(new_person)
# 清除ali节点所有的know关系
ali.knows.clear()
# 清除ali节点指向new_person的那个know关系
ali.knows.remove(new_person)
# 更新ali指向new_person关系的属性值
ali.knows.update(new_person,year=5)
# 获取ali指向new_person关系的属性year的值
ali.knows.get(new_person,'year')

グラフオブジェクトを介して、ノードと関係を一致させるためにmatchメソッドを呼び出すこともできます

# 获取第一个主键name名为Alice的Person对象
ali = Person.match(graph, 'Alice').first()
# 获取所有name以B开头的Person对象
Person.match(graph).where("_.name =~ 'B.*'")

グラフを通じてノードオブジェクトを操作することもできます。

# 更新图中ali节点的相关数据
graph.push(ali)
# 用图中的信息来更新ali节点
graph.pull(ali)
# 删除图中的ali对象节点
graph.delete(ali)
元の記事124件を公開 65のような 130,000 以上を 訪問

おすすめ

転載: blog.csdn.net/theVicTory/article/details/100527171