最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python使用py2neo查詢Neo4j的節(jié)點(diǎn)、關(guān)系及路徑

 更新時(shí)間:2021年08月24日 15:20:39   作者:流浪貓貓  
本文介紹了使用Py2neo的NodeMatcher和RelationshipMatcher查詢圖中的節(jié)點(diǎn)和關(guān)系,以及通過(guò)執(zhí)行Cypher語(yǔ)句的查詢方式。感興趣的小伙伴請(qǐng)看下文

Neo4j是一款開(kāi)源圖數(shù)據(jù)庫(kù),Py2neo提供了使用Python語(yǔ)言訪問(wèn)Neo4j的接口。本文介紹了使用Py2neo的NodeMatcher和RelationshipMatcher查詢圖中的節(jié)點(diǎn)和關(guān)系,以及通過(guò)執(zhí)行Cypher語(yǔ)句的查詢方式。​本文使用的Py2neo是2021.1之后的版本,手冊(cè)請(qǐng)戳這里:
The Py2neo Handbook

一、連接Neo4j數(shù)據(jù)庫(kù)

本文中會(huì)用到多種數(shù)據(jù)類型,在此一并引用

<import numpy as np
import pandas as pd
from py2neo import Node,Relationship,Graph,Path,Subgraph
from py2neo import NodeMatcher,RelationshipMatcher

配置Neo4j數(shù)據(jù)庫(kù)的訪問(wèn)地址、用戶名和密碼:

neo4j_url = '訪問(wèn)地址'
user = '用戶名'
pwd = '密碼'

在此時(shí)間段之前訪問(wèn)數(shù)據(jù)庫(kù)的方式為:

graph = Graph(neo4j_url, username=user, password=pwd)

在此時(shí)間段之后的版本訪問(wèn)數(shù)據(jù)庫(kù)的方式為(就是這么不兼容):

graph = Graph(neo4j_url,  auth=(user, pwd))

以下圖為例:

  • 圖中包含一些Person節(jié)點(diǎn),每個(gè)Person節(jié)點(diǎn)有name、age、work屬性;
  • 其中“趙趙”節(jié)點(diǎn)是多l(xiāng)abel的節(jié)點(diǎn),除了有Person標(biāo)簽,它還有Teacher標(biāo)簽;
  • Person和Person節(jié)點(diǎn)之間有同事、鄰居、學(xué)生、老師等關(guān)系;
  • 圖中還有一些Location節(jié)點(diǎn),它們之間有包含關(guān)系;
  • Person節(jié)點(diǎn)和Location節(jié)點(diǎn)之間有“到訪”關(guān)系,“到訪”關(guān)系具有date和stay_hours兩個(gè)屬性。

二、 通過(guò)graph.schema查詢圖中節(jié)點(diǎn)和關(guān)系有哪些類型

查看節(jié)點(diǎn)的類型用graph.schema.node_labels,查看關(guān)系的類型用graph.schema.relationship_types,它們的返回值類型都是frozenset,是不能增刪元素的集合。

>>>graph.schema.node_labels 
frozenset({'Location', 'Person', 'Teacher'})
>>>graph.schema.relationship_types
frozenset({'到訪', '包含', '同事', '學(xué)生', '老師', '鄰居'})


三、使用NodeMatcher查詢節(jié)點(diǎn)

首先創(chuàng)建一個(gè)NodeMatcher對(duì)象,用match來(lái)指明要匹配哪種label的節(jié)點(diǎn),用where來(lái)表示篩選條件(有兩種方法)。需要注意的是,匹配成功返回的是NodeMatcher的對(duì)象,要轉(zhuǎn)化成Node對(duì)象,可以用first取出符合條件的第一個(gè)節(jié)點(diǎn),或者轉(zhuǎn)化成節(jié)點(diǎn)的list。

>>>node_matcher = NodeMatcher(graph)
>>>node = node_matcher.match("Person").where(age=20).first()
>>>node
Node('Person', age=20, name='李李', work='腳本之家')
>>>nodes = list(node_matcher.match("Person").where(age=35))
>>>nodes
[Node('Person', age=35, name='王王', work='腳本之家')]

where條件有兩種寫(xiě)法,一種是把要匹配的屬性和值寫(xiě)成key=value的形式,例如上面的where(age=20),這種寫(xiě)法只能按照值是否完全一致來(lái)匹配,不能按照值的大小來(lái)篩選,如果寫(xiě)成下面這樣是會(huì)報(bào)錯(cuò)的:

node = node_matcher.match("Person").where(age>20).first() # 錯(cuò)誤
想要按照值的大小篩選或者做一些字符串的模糊匹配,可以把條件表達(dá)式寫(xiě)成一個(gè)字符串,整體放在where語(yǔ)句中,在這個(gè)字符串中,可以用 _ 來(lái)代指匹配到的節(jié)點(diǎn)。下面兩個(gè)例子,第一個(gè)是匹配work屬性為“月亮XX”模式的Person節(jié)點(diǎn),另一個(gè)是匹配age大于20的Person節(jié)點(diǎn)。

>>>node = node_matcher.match("Person").where("_.work =~ '月亮.*'").first()
>>>node
Node('Person', 'Teacher', age=45, name='趙趙', work='月亮中學(xué)')
>>>nodes = list(node_matcher.match("Person").where("_.age > 20"))
>>>nodes
[Node('Person', age=35, name='王王', work='腳本之家'),
 Node('Person', age=30, name='張張', work='腳本之家'),
 Node('Person', 'Teacher', age=45, name='趙趙', work='月亮中學(xué)')]

將NodeMatcher返回的結(jié)果轉(zhuǎn)化為Node數(shù)據(jù)類型或者Node的list之后,訪問(wèn)其中的屬性也就十分簡(jiǎn)單了,如上面最后一例的結(jié)果,訪問(wèn)其中第一個(gè)節(jié)點(diǎn)的name屬性:

>>>nodes[0]['name']
'王王'

四、 使用RelationshipMatcher查詢關(guān)系

RelationshipMatcher的match方法有三個(gè)及以上參數(shù):

  • 第一個(gè)參數(shù)是節(jié)點(diǎn)的序列或者set,可以為None,為None表示任意節(jié)點(diǎn)均可;
  • 第二個(gè)參數(shù)是關(guān)系的類型,可以為None,為None表示任意類型的關(guān)系均可;
  • 第三個(gè)參數(shù)開(kāi)始是要匹配的屬性,寫(xiě)成key=value的形式。

match方法的返回值是RelationshipMatcher類型,需要通過(guò)first轉(zhuǎn)化成Relationship數(shù)據(jù)結(jié)構(gòu),或者轉(zhuǎn)化為list。

舉例說(shuō)明

列1:比如想要查詢“李李”節(jié)點(diǎn)的所有關(guān)系。先查詢出節(jié)點(diǎn),再查詢節(jié)點(diǎn)的關(guān)系,r_type=None表示任意類型的關(guān)系均可。返回的關(guān)系包括到訪、同事。

>>>node1 = node_matcher.match("Person").where(name='李李').first()
>>>relationship = list(relationship_matcher.match([node1], r_type=None))
>>>relationship
[到訪(Node('Person', age=20, name='李李', work='腳本之家'), Node('Location', name='祿口機(jī)場(chǎng)'), date='2021/7/16', stay_hours=1),
 同事(Node('Person', age=20, name='李李', work='腳本之家'), Node('Person', age=30, name='張張', work='腳本之家')),
 同事(Node('Person', age=20, name='李李', work='腳本之家'), Node('Person', age=35, name='王王', work='腳本之家'))]


例2:查詢“李李”和“張張”的關(guān)系,兩個(gè)節(jié)點(diǎn)的順序表示了要匹配的關(guān)系的方向。所以在整個(gè)圖中“李李”和“張張”節(jié)點(diǎn)之間的同事關(guān)系是雙向的,但是查詢結(jié)果只給出了從“張張”節(jié)點(diǎn)到“李李”節(jié)點(diǎn)的一條關(guān)系。

>>>node1 = node_matcher.match("Person").where(name='李李').first()
>>>node2 = node_matcher.match("Person").where(name='張張').first()
>>>relationship = list(relationship_matcher.match((node2,node1), r_type=None))
>>>relationship
[同事(Node('Person', age=30, name='張張', work='腳本之家'), Node('Person', age=20, name='李李', work='腳本之家'))]

例3:詢圖中某一類關(guān)系,第一個(gè)參數(shù)為None,第二個(gè)參數(shù)r_type指定關(guān)系類型,這里查詢了圖中所有的同事關(guān)系。

>>>relationship = list(relationship_matcher.match(None, r_type='同事'))
>>>relationship
[同事(Node('Person', age=20, name='李李', work='腳本之家'), Node('Person', age=30, name='張張', work='腳本之家')),
 同事(Node('Person', age=20, name='李李', work='腳本之家'), Node('Person', age=35, name='王王', work='腳本之家')),
 同事(Node('Person', age=35, name='王王', work='腳本之家'), Node('Person', age=20, name='李李', work='腳本之家')),
 同事(Node('Person', age=30, name='張張', work='腳本之家'), Node('Person', age=20, name='李李', work='腳本之家'))]


例4: 在查詢關(guān)系時(shí)按照屬性的值篩選,可以將該屬性寫(xiě)為key=value的形式作為match方法的第三個(gè)參數(shù)。這里,查詢圖中的到訪關(guān)系,并且stay_hours屬性為1。

>>>relationship = list(relationship_matcher.match(None, r_type='到訪', stay_hours=1))
>>>relationship
[到訪(Node('Person', age=20, name='李李', work='腳本之家'), Node('Location', name='祿口機(jī)場(chǎng)'), date='2021/8/24', stay_hours=1)]

雖然Py2neo的手冊(cè)上沒(méi)有寫(xiě),但其實(shí)RelationshipMatcher也可以接上where方法,按照屬性的值篩選關(guān)系。上面這個(gè)例子也可以寫(xiě)作下面這種形式,效果是一樣的。

relationship = list(relationship_matcher.match(None, r_type='到訪').where(stay_hours=1))
同樣,在where方法中也可以寫(xiě)一個(gè)字符串表達(dá)式,實(shí)現(xiàn)按值大小來(lái)篩選關(guān)系。例如要篩選出所有到訪關(guān)系,且stay_hours>=1的關(guān)系時(shí),可以這樣寫(xiě):

>>>relationship = list(relationship_matcher.match(None, r_type='到訪').where("_.stay_hours>=1"))
>>>relationship
[到訪(Node('Person', age=20, name='李李', work='腳本之家'), Node('Location', name='祿口機(jī)場(chǎng)'), date='2021/8/24', stay_hours=1),
 到訪(Node('Person', age=20, name='劉劉', work='地球電子商務(wù)公司'), Node('Location', name='祿口機(jī)場(chǎng)'), date='2021/8/24', stay_hours=4)]

如何訪問(wèn)返回的結(jié)果中的各個(gè)屬性呢,Relationship其實(shí)是包含了一對(duì)起止節(jié)點(diǎn):start_nodeend_node,包含了關(guān)系的類型,而關(guān)系的屬性是以字典形式存在的,可以用get方法來(lái)獲取屬性的值。
獲取關(guān)系的起止節(jié)點(diǎn):

>>>print(relationship[0].start_node['name'])
>>>print(relationship[0].end_node['name'])
李李
祿口機(jī)場(chǎng)

獲取關(guān)系的類型的文本字符串

>>>print(relationship[0])
>>>print(type(relationship[0]).__name__)
(李李)-[:到訪 {date: '2021/8/24', stay_hours: 1}]->(祿口機(jī)場(chǎng))
到訪

獲取關(guān)系中的屬性和值

>>>print(relationship[0].keys())
>>>print(relationship[0].values())
>>>print(relationship[0].get('date'))
dict_keys(['date', 'stay_hours'])
dict_values(['2021/8/24', 1])
2021/8/24

五、通過(guò)執(zhí)行Cypher語(yǔ)句查詢

NodeMatcher和RelationshipMatcher能夠表達(dá)的匹配條件相對(duì)簡(jiǎn)單,更加復(fù)雜的查詢還是需要用Cypher語(yǔ)句來(lái)表達(dá)。Py2neo本身支持執(zhí)行Cypher語(yǔ)句的執(zhí)行,可以將復(fù)雜的查詢寫(xiě)成Cypher語(yǔ)句,通過(guò)graph.run方法查詢,返回的結(jié)果可以轉(zhuǎn)化為pandas.DataFrame或者pandas.Series對(duì)象,從而和其他數(shù)據(jù)分析工具無(wú)縫銜接。

例如:要查詢Person節(jié)點(diǎn),并滿足work屬性為“腳本之家”。Cypher語(yǔ)句中可以使用WHERE接條件表達(dá)式,使用AS將返回的屬性改名,返回多個(gè)屬性時(shí),用xxx AS x, yyy AS y。graph.run方法之后再接to_data_frame()可以將返回的數(shù)據(jù)變成pandas的DataFrame對(duì)象,并且用AS改過(guò)的屬性名即為DataFrame中的列名。

cypher_ = "MATCH (n:Person) \
WHERE n.work='腳本之家' \
RETURN n.name AS name, n.age AS age "

df = graph.run(cypher_).to_data_frame() # pd.DataFrame

例2:查詢一個(gè)已知節(jié)點(diǎn)和其他哪些節(jié)點(diǎn)有關(guān)系,有什么樣的關(guān)系。Cypher語(yǔ)言查詢關(guān)系時(shí)用 < 或者 > 表示方向,這里需要返回type(r),直接返回r的話結(jié)果里是空值。

>>>cypher_ = "MATCH (n:Person)-[r]->(m:Person) \
WHERE n.name='李李' \
RETURN type(r) AS type,m.name AS name"
>>>df = graph.run(cypher_).to_data_frame() # pd.DataFrame

例3:Cypher語(yǔ)言還可以查詢路徑,因?yàn)椴淮_定返回的路徑數(shù)量,所以最好先將結(jié)果轉(zhuǎn)化為pandas.Series,再遍歷訪問(wèn)其中每條路徑的節(jié)點(diǎn)和關(guān)系。
這里查詢的是“趙趙”節(jié)點(diǎn)和“王王”節(jié)點(diǎn)之間的關(guān)系路徑,關(guān)系指定為同事或鄰居,關(guān)系不超過(guò)4層。

>>>cypher_ = "MATCH path=(m:Person)-[:同事|鄰居*1..4]->(n:Person) \
WHERE m.name='趙趙' AND n.name='王王' \
RETURN path"
>>>s = graph.run(cypher_).to_series()
>>>print(len(s))
>>>s[0]

Path(Node('Person', 'Teacher', age=45, name='趙趙', work='月亮中學(xué)'),
鄰居(Node('Person', 'Teacher', age=45, name='趙趙', work='月亮中學(xué)'), 
Node('Person', age=30, name='張張', work='腳本之家')), 
同事(Node('Person', age=30, name='張張', work='腳本之家'), 
Node('Person', age=20, name='李李', work='腳本之家')), 
同事(Node('Person', age=20, name='李李', work='腳本之家'), 
Node('Person', age=35, name='王王', work='腳本之家')))

這里查詢到的關(guān)系路徑數(shù)量?jī)H有1條。從上圖的結(jié)果中也可以看出來(lái),Path是一個(gè)比較復(fù)雜的結(jié)構(gòu),Path中的節(jié)點(diǎn)和關(guān)系分別用nodes和relationships表示,并且是按照路徑上節(jié)點(diǎn)和關(guān)系的順序分別存放的。這里給出一段示例代碼,對(duì)每一個(gè)路徑都做了直接打印path數(shù)據(jù)結(jié)構(gòu)和自己組織路徑文本。

for path in s:
    # 直接打印path
    print(path)
    # 獲取路徑中的節(jié)點(diǎn)和關(guān)系
    nodes = path.nodes
    relationshis = path.relationships   
    # 自己組織路徑文本
    path_text = ""
    for n,r in zip(nodes, relationshis):
        # 每次加入一個(gè)節(jié)點(diǎn)和一個(gè)關(guān)系的類型
        path_text += "{} - {} - ".format(n['name'], type(r).__name__)
    # 別忘了最后一個(gè)節(jié)點(diǎn)
    path_text += nodes[-1]['name'] + '\n'
    print(path_text)

運(yùn)行這段代碼得的結(jié)果如下所示,上面一行是直接打印路徑的結(jié)果,下面一行是自己組織文本得到的結(jié)果。

(趙趙)-[:鄰居 {}]->(張張)-[:同事 {}]->(李李)-[:同事 {}]->(王王)
趙趙 - 鄰居 - 張張 - 同事 - 李李 - 同事 - 王王

使用Py2neo查詢Neo4j中的節(jié)點(diǎn)、關(guān)系和路徑時(shí),條件簡(jiǎn)單的查詢可以通NodeMatcher和RelationshipMatcher來(lái)實(shí)現(xiàn)。而較為復(fù)雜的查詢,可以寫(xiě)成Cypher語(yǔ)句來(lái)查詢,查詢結(jié)果可以轉(zhuǎn)化為pandas的DataFrame或者Series數(shù)據(jù)類型,與其他數(shù)據(jù)分析工具結(jié)合

 以上就是python使用py2neo查詢Neo4j的節(jié)點(diǎn)、關(guān)系及路徑的詳細(xì)內(nèi)容,更多關(guān)于python py2neo的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python opencv 讀取本地視頻文件 修改ffmpeg的方法

    python opencv 讀取本地視頻文件 修改ffmpeg的方法

    今天小編就為大家分享一篇python opencv 讀取本地視頻文件 修改ffmpeg的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Python中用xlwt制作表格實(shí)例講解

    Python中用xlwt制作表格實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于Python中用xlwt制作表格實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2020-11-11
  • python區(qū)塊鏈實(shí)現(xiàn)簡(jiǎn)版工作量證明

    python區(qū)塊鏈實(shí)現(xiàn)簡(jiǎn)版工作量證明

    這篇文章主要為大家介紹了python區(qū)塊鏈實(shí)現(xiàn)簡(jiǎn)版工作量證明詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • python爬取網(wǎng)易云音樂(lè)評(píng)論

    python爬取網(wǎng)易云音樂(lè)評(píng)論

    這篇文章主要為大家詳細(xì)介紹了python爬取網(wǎng)易云音樂(lè)評(píng)論,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • python字符串分割常用方法(str.split()和正則)

    python字符串分割常用方法(str.split()和正則)

    在Python中字符串是一種非常常見(jiàn)的數(shù)據(jù)類型,在實(shí)際應(yīng)用中我們經(jīng)常需要對(duì)字符串進(jìn)行分割,以便對(duì)其中的內(nèi)容進(jìn)行處理,這篇文章主要給大家介紹了關(guān)于python字符串分割(str.split()和正則)的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • python開(kāi)發(fā)中兩個(gè)list之間傳值示例

    python開(kāi)發(fā)中兩個(gè)list之間傳值示例

    這篇文章主要介紹了python開(kāi)發(fā)中兩個(gè)list列表之間傳值的方法,有需要的朋友可以借鑒參考下,希望可以有所幫助,希望大家共同學(xué)習(xí),共同進(jìn)步
    2021-09-09
  • python正則表達(dá)式re模塊的使用示例詳解

    python正則表達(dá)式re模塊的使用示例詳解

    這篇文章主要為大家介紹了python正則表達(dá)式re模塊的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • flask解析??禂z像頭視頻的使用

    flask解析海康攝像頭視頻的使用

    本文主要介紹了flask解析??禂z像頭視頻的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Python海象運(yùn)算符的用法教程

    Python海象運(yùn)算符的用法教程

    Python 海象運(yùn)算符是在 PEP 572 中提出,并在 Python3.8 版本并入和發(fā)布。本文就來(lái)為大家詳細(xì)講講Python海象運(yùn)算符的用法,感興趣的可以了解一下
    2022-07-07
  • Python socket聊天腳本代碼實(shí)例

    Python socket聊天腳本代碼實(shí)例

    這篇文章主要介紹了Python socket聊天腳本代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01

最新評(píng)論

定远县| 杂多县| 涞水县| 廊坊市| 嘉定区| 盘锦市| 凤庆县| 嘉义市| 孟津县| 随州市| 凯里市| 元氏县| 白朗县| 斗六市| 高碑店市| 宜黄县| 丰城市| 保康县| 伽师县| 永和县| 北流市| 托克托县| 连云港市| 南华县| 霍邱县| 长子县| 新宁县| 唐河县| 左权县| 祁东县| 平原县| 长葛市| 民丰县| 崇仁县| 沈阳市| 墨竹工卡县| 同仁县| 泸定县| 于田县| 涞水县| 怀仁县|