• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    python使用py2neo查询Neo4j的节点、关系及路径

    Neo4j是一款开源图数据库,Py2neo提供了使用Python语言访问Neo4j的接口。本文介绍了使用Py2neo的NodeMatcher和RelationshipMatcher查询图中的节点和关系,以及通过执行Cypher语句的查询方式。​本文使用的Py2neo是2021.1之后的版本,手册请戳这里:
    The Py2neo Handbook

    一、连接Neo4j数据库

    本文中会用到多种数据类型,在此一并引用

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

    配置Neo4j数据库的访问地址、用户名和密码:

    neo4j_url = '访问地址'
    user = '用户名'
    pwd = '密码'
    
    

    在此时间段之前访问数据库的方式为:

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

    在此时间段之后的版本访问数据库的方式为(就是这么不兼容):

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

    以下图为例:

    二、 通过graph.schema查询图中节点和关系有哪些类型

    查看节点的类型用graph.schema.node_labels,查看关系的类型用graph.schema.relationship_types,它们的返回值类型都是frozenset,是不能增删元素的集合。

    >>>graph.schema.node_labels 
    frozenset({'Location', 'Person', 'Teacher'})
    >>>graph.schema.relationship_types
    frozenset({'到访', '包含', '同事', '学生', '老师', '邻居'})
    
    
    

    三、使用NodeMatcher查询节点

    首先创建一个NodeMatcher对象,用match来指明要匹配哪种label的节点,用where来表示筛选条件(有两种方法)。需要注意的是,匹配成功返回的是NodeMatcher的对象,要转化成Node对象,可以用first取出符合条件的第一个节点,或者转化成节点的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条件有两种写法,一种是把要匹配的属性和值写成key=value的形式,例如上面的where(age=20),这种写法只能按照值是否完全一致来匹配,不能按照值的大小来筛选,如果写成下面这样是会报错的:

    node = node_matcher.match("Person").where(age>20).first() # 错误
    想要按照值的大小筛选或者做一些字符串的模糊匹配,可以把条件表达式写成一个字符串,整体放在where语句中,在这个字符串中,可以用 _ 来代指匹配到的节点。下面两个例子,第一个是匹配work属性为“月亮XX”模式的Person节点,另一个是匹配age大于20的Person节点。

    >>>node = node_matcher.match("Person").where("_.work =~ '月亮.*'").first()
    >>>node
    Node('Person', 'Teacher', age=45, name='赵赵', work='月亮中学')
    >>>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='月亮中学')]

    将NodeMatcher返回的结果转化为Node数据类型或者Node的list之后,访问其中的属性也就十分简单了,如上面最后一例的结果,访问其中第一个节点的name属性:

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

    四、 使用RelationshipMatcher查询关系

    RelationshipMatcher的match方法有三个及以上参数:

    match方法的返回值是RelationshipMatcher类型,需要通过first转化成Relationship数据结构,或者转化为list。

    举例说明

    列1:比如想要查询“李李”节点的所有关系。先查询出节点,再查询节点的关系,r_type=None表示任意类型的关系均可。返回的关系包括到访、同事。

    >>>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='禄口机场'), 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:查询“李李”和“张张”的关系,两个节点的顺序表示了要匹配的关系的方向。所以在整个图中“李李”和“张张”节点之间的同事关系是双向的,但是查询结果只给出了从“张张”节点到“李李”节点的一条关系。

    >>>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:询图中某一类关系,第一个参数为None,第二个参数r_type指定关系类型,这里查询了图中所有的同事关系。

    >>>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: 在查询关系时按照属性的值筛选,可以将该属性写为key=value的形式作为match方法的第三个参数。这里,查询图中的到访关系,并且stay_hours属性为1。

    >>>relationship = list(relationship_matcher.match(None, r_type='到访', stay_hours=1))
    >>>relationship
    [到访(Node('Person', age=20, name='李李', work='脚本之家'), Node('Location', name='禄口机场'), date='2021/8/24', stay_hours=1)]

    虽然Py2neo的手册上没有写,但其实RelationshipMatcher也可以接上where方法,按照属性的值筛选关系。上面这个例子也可以写作下面这种形式,效果是一样的。

    relationship = list(relationship_matcher.match(None, r_type='到访').where(stay_hours=1))
    同样,在where方法中也可以写一个字符串表达式,实现按值大小来筛选关系。例如要筛选出所有到访关系,且stay_hours>=1的关系时,可以这样写:

    >>>relationship = list(relationship_matcher.match(None, r_type='到访').where("_.stay_hours>=1"))
    >>>relationship
    [到访(Node('Person', age=20, name='李李', work='脚本之家'), Node('Location', name='禄口机场'), date='2021/8/24', stay_hours=1),
     到访(Node('Person', age=20, name='刘刘', work='地球电子商务公司'), Node('Location', name='禄口机场'), date='2021/8/24', stay_hours=4)]

    如何访问返回的结果中的各个属性呢,Relationship其实是包含了一对起止节点:start_nodeend_node,包含了关系的类型,而关系的属性是以字典形式存在的,可以用get方法来获取属性的值。
    获取关系的起止节点:

    >>>print(relationship[0].start_node['name'])
    >>>print(relationship[0].end_node['name'])
    李李
    禄口机场

    获取关系的类型的文本字符串

    >>>print(relationship[0])
    >>>print(type(relationship[0]).__name__)
    (李李)-[:到访 {date: '2021/8/24', stay_hours: 1}]->(禄口机场)
    到访

    获取关系中的属性和值

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

    五、通过执行Cypher语句查询

    NodeMatcher和RelationshipMatcher能够表达的匹配条件相对简单,更加复杂的查询还是需要用Cypher语句来表达。Py2neo本身支持执行Cypher语句的执行,可以将复杂的查询写成Cypher语句,通过graph.run方法查询,返回的结果可以转化为pandas.DataFrame或者pandas.Series对象,从而和其他数据分析工具无缝衔接。

    例如:要查询Person节点,并满足work属性为“脚本之家”。Cypher语句中可以使用WHERE接条件表达式,使用AS将返回的属性改名,返回多个属性时,用xxx AS x, yyy AS y。graph.run方法之后再接to_data_frame()可以将返回的数据变成pandas的DataFrame对象,并且用AS改过的属性名即为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:查询一个已知节点和其他哪些节点有关系,有什么样的关系。Cypher语言查询关系时用 或者 > 表示方向,这里需要返回type(r),直接返回r的话结果里是空值。

    >>>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语言还可以查询路径,因为不确定返回的路径数量,所以最好先将结果转化为pandas.Series,再遍历访问其中每条路径的节点和关系。
    这里查询的是“赵赵”节点和“王王”节点之间的关系路径,关系指定为同事或邻居,关系不超过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='月亮中学'),
    邻居(Node('Person', 'Teacher', age=45, name='赵赵', work='月亮中学'), 
    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='脚本之家')))

    这里查询到的关系路径数量仅有1条。从上图的结果中也可以看出来,Path是一个比较复杂的结构,Path中的节点和关系分别用nodes和relationships表示,并且是按照路径上节点和关系的顺序分别存放的。这里给出一段示例代码,对每一个路径都做了直接打印path数据结构和自己组织路径文本。

    for path in s:
        # 直接打印path
        print(path)
        # 获取路径中的节点和关系
        nodes = path.nodes
        relationshis = path.relationships   
        # 自己组织路径文本
        path_text = ""
        for n,r in zip(nodes, relationshis):
            # 每次加入一个节点和一个关系的类型
            path_text += "{} - {} - ".format(n['name'], type(r).__name__)
        # 别忘了最后一个节点
        path_text += nodes[-1]['name'] + '\n'
        print(path_text)

    运行这段代码得的结果如下所示,上面一行是直接打印路径的结果,下面一行是自己组织文本得到的结果。

    (赵赵)-[:邻居 {}]->(张张)-[:同事 {}]->(李李)-[:同事 {}]->(王王)
    赵赵 - 邻居 - 张张 - 同事 - 李李 - 同事 - 王王

    使用Py2neo查询Neo4j中的节点、关系和路径时,条件简单的查询可以通NodeMatcher和RelationshipMatcher来实现。而较为复杂的查询,可以写成Cypher语句来查询,查询结果可以转化为pandas的DataFrame或者Series数据类型,与其他数据分析工具结合

     以上就是python使用py2neo查询Neo4j的节点、关系及路径的详细内容,更多关于python py2neo的资料请关注脚本之家其它相关文章!

    您可能感兴趣的文章:
    • Python使用Py2neo创建Neo4j的节点与关系
    • Python使用py2neo操作图数据库neo4j的方法详解
    • python利用文件读写编写一个博客
    • 手把手带你用python爬取小姐姐私房照
    • Python time.time()方法
    • Python接口自动化之接口依赖
    • python中bottle使用实例代码
    上一篇:用Python做一个哔站小姐姐词云跳舞视频
    下一篇:用python爬取分析淘宝商品信息详解技术篇
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    python使用py2neo查询Neo4j的节点、关系及路径 python,使用,py2neo,查询,Neo4j,