作者简介:20年IT工作经验,曾在华为、HP、移动、电网等国内外知名IT企业任职;关注领域包括证券、航空、制造、电信、电网等。在数据库开发和优化、数据仓库、系统架构、大中型项目管理、部门管理、数据挖掘和分析、数据治理、大数据方面有一定研究。


关于Neo4j图数据库

一、关于neo4j图数据库的下载、安装和配置

1、下载,建议从官网下载社区版本

ftp://neo4j.55555.io/neo4j/3.5.12/neo4j-community-3.5.12-windows.zip

ftp://neo4j.55555.io/neo4j-doc/3.5/

2、预安装,确保java已安装

执行java –version命令,检查java是否已安装

3、安装步骤,很简单,不必赘述

4、安装后的环境变量配置

SET NEO4J_HOME=c:\neo4j

SET PATH=% NEO4J_HOME %\BIN

5、以管理员身份在命令窗口执行neo4j.bat console

6、通过IE打开http://localhost:7474/,建议打开http://127.0.0.1:7474/

7、设置用户名和密码

8、打开主页面

9、neo4j的几个命令

neo4j install-serviceneo4j startneo4j stopneo4j restartneo4j status

10、部分问题和困扰

问题1、好像neo4j.batconsole和neo4j start无法共存

启动了neo4j.bat console,就无法启动neo4j start,反之亦然

问题2、另外访问neo4j首页,建议通过IP地址访问http://127.0.0.1:7474/browser/,否则无法正常连接neo4j数据库

二、关于neo4j图数据库的一些粗浅认识

A graph database can store any kind of data usinga few simple concepts:

1.Nodes - graph data records

2.Relationships - connect nodes

3.Properties - named data values

图数据库包括节点、关系和属性。

节点由标签和一系列属性构成,

#neo4j代码CREATE (ee:Person { name: "Emil", from:"Sweden", klout: 99 })#Python代码a = Node("Person", name="Alice",createdate=’2019-02-02’)标签等同于数据库中的表,name意味着值的名称,在这里姑且认为是主键值吧,可以想想如何确保数据表中的数据的唯一性吧,后面的属性可以根据需要进行定制

关于关系,是节点和节点之间的连接,当然关系也可以设置很多明细的属性

#neo4j代码CREATE (ee)-[:KNOWS {since: 2001}]->(js),(ee)-[:KNOWS{rating: 5}]->(ir)#Python代码ab = Relationship(a, "KNOWS", b)ab=Relationship(test_node_2,'妻子',test_node_1)

关系查找,如果一个系统只存储而不能查找,这个系统大概是没什么价值的,neo4j是通过match来进行查找的。

#neo4j代码MATCH (ee:Person) WHERE ee.name = "Emil" RETURNee;#Python代码list(matcher.match("Person").where("_.name =~ 'K.*'"))

三,我要做的事情,是把各系统架构类的东西以图的形式呈现出来,形成所谓的知识图谱,可以基于业务视角呈现各系统之间的耦合关系,可以基于数据库的视角,能够查看各业务系统之间的相互依赖,也可以以机房机柜角度查看,当然这只是初衷,也许会随着对图数据库的知识的认识深度变化而变化。这只是个开始。

py2neo使用

neo4j是个图数据库,所有的数据库都要通过语言去访问,一个封闭的系统是没有意义的,在python里也提供了基于neo4j的package,不过使用最广的还是py2neo,提供对图库的连接和增删改查操作,本文也遵循这个思路,先从基本语法做起,后面才慢慢丰富完善,至少先看到一些成果。

还是一句话,网上的材料看似很丰富,但良莠不齐,有的缺乏深度有的是抄袭有的甚至无法运行,所有的材料要自己看过试过,所以非常感谢下面链接的仁兄的做事态度,对相关代码略作修改,完善并使用起来。

https://www.cnblogs.com/Bw98blogs/p/10946569.html

from py2neo import Graph, Node, Relationship, NodeMatcher

class Neo4jDao:

    #初始化用户名密码    def __init__(self, username='neo4j', password='Wbq197711'):        self.username = username        self.password = password        self.my_graph = self.connectNeo4j(username=self.username, password=self.password)

    @staticmethod    def connectNeo4j(username:str, password: str):        #初始化图数据库连接        my_graph = Graph(            "http://localhost:7474",            username=username,            password=password        )        return my_graph

    def createNode(self, label: str, properties:dict):        #创建结点,如果结点有类型和属性的话,也一起创建        #:param label: 结点的类型        #:param properties: 多个属性键值对组成的字典,用于初始化结点的属性        #:return:创建好的结点,类型为Node        node = Node(label, **properties)        self.my_graph.create(node)        return node

    def createRelationship(self, start_node: Node, relation_type: str, end_node: Node, relation_properties=None):        #创建关系,如果有关系上属性的话就一起创建        #:param start_node: 起始结点        #:param relation_type: 关系类型        #:param end_node: 结束结点        #:param relation_properties: 属性字典,如果有传入的话,则在关系上添加多个形如"属性名:属性值"的键值对        #:return: 创建好的关系对象        new_relation = Relationship(start_node, relation_type, end_node)        new_relation.update(relation_properties)        self.my_graph.create(new_relation)        return new_relation

    def updateProperty(self, node_or_relation, aProperty: tuple):        #更新节点和关系的属性        #:param node_or_relation: 一个结点或关系对象        #:param aProperty: 需要更新的"属性名:属性值"键值对组成的字典        #:return:

        # 判断节点和关系是否正确,如果更新属性        if (not isinstance(node_or_relation, Node)) and (not isinstance((node_or_relation, Relationship))):            raise TypeError('node_or_relation 需要是 Node 或 Relationship 类型')        node_or_relation[aProperty[0]] = aProperty[1]  # tuple的第一位存属性名,第二位存属性值        self.my_graph.push(node_or_relation)

    @staticmethod    def updateMultipleProperty(node_or_relation, properties: dict):        #同时更新多个属性        #:param node_or_relation: 一个结点或关系对象        #:param properties: 多个需要更新的"属性名:属性值"键值对组成的字典        #:return:

        #判断节点和关系是否正确,如果更新属性        if (not isinstance(node_or_relation, Node)) and (not isinstance((node_or_relation, Relationship))):            raise TypeError('node_or_relation 需要是 Node 或 Relationship 类型')        node_or_relation.update(properties)

    def findOneNode(self, node_type=None, properties=None, where=None):        #查找一个结点        #:param node_type:结点类型,即 label,类型是str        #:param properties: 多个"属性名: 属性值"键值对组成的字典,类型是dict        #:param where: 查询子句,类型是str        #:return: 一个Node类型的结点

        #初始化节点匹配实例        matcher = NodeMatcher(self.my_graph)        #节点判断        if not (isinstance(node_type, str)):            raise TypeError('查询的结点的类型必须要指定,而且node_type必须是字符串类型')        #属性字典判断        if not (properties is None):            if not (isinstance(properties, dict)):                raise TypeError('properties是多个属性键值对组成的字典,它必须是dict类型')        #where条件判断        if not (where is None):            if not (isinstance(where, str)):                raise TypeError('where表示的是查询条件,它必须是字符串类型')        #组合条件判断,以匹配相关match函数,并返回单一节点        if (where is None) and (properties is None):            return matcher.match(node_type).first()        elif (not (properties is None)) and (where is None):            return matcher.match(node_type, **properties).first()        elif (properties is None) and (not (where is None)):            return matcher.match(node_type).where(where).first()

    def findAllNode(self, node_type=None, properties=None, where=None):        #查找多个结点        #:param node_type: node_type:结点类型,即 label,类型是str        #:param properties: 多个"属性名: 属性值"键值对组成的字典,类型是dict        #:param where: 查询子句,类型是str        #:return: 多个Node类型的结点组成的list,类型是list

        #初始化节点匹配实例        matcher = NodeMatcher(self.my_graph)        #节点判断        if not (isinstance(node_type, str)):            raise TypeError('查询的结点的类型必须要指定,而且node_type必须是字符串形式')        #where条件判断        if not (where is None):            if not (isinstance(where, str)):                raise TypeError('where表示的是查询条件,它必须是字符串形式')        #组合条件判断,以匹配相关match函数,并返回节点list        #如果属性和where均为None        if (properties is None) and (where is None):            res = matcher.match(node_type)            if len(list(res)) > 0:                return list(res)            else:                return None        #属性不为None,where为None        elif (not (properties is None)) and (where is None):            res = matcher.match(node_type, **properties)            if len(list(res)) > 0:                return list(res)            else:                return None        ##属性为None,where不为None        elif (properties is None) and (not (where is None)):            res = matcher.match(node_type).where(where)            if len(list(res)) > 0:                return list(res)            else:                return None

    def findOneRelationship(self, nodes=None, r_type=None):        #查找一条关系        #:param nodes: 要查找的结点集合,比如[起点,终点],这个参数可以没有        #:param r_type: 要查找的关系的类型        #:return:  None 或者 一条查询结果

        #组合条件判断,以匹配相关match_one函数,并返回关系        if (nodes is None) and (r_type is None):            raise TypeError('nodes 和 r_type 必须有一个是非空')        elif (not (nodes is None)) and (not (r_type is None)):            return self.my_graph.match_one(nodes=nodes, r_type=r_type)        elif (not (nodes is None)) and (r_type is None):            return self.my_graph.match_one(nodes=nodes)        elif (nodes is None) and (not (r_type is None)):            return self.my_graph.match_one(r_type=r_type)

    def findAllRelationship(self, nodes=None, r_type=None):        #查找多条关系        #:param nodes: 要查找的结点集合,比如[起点,终点],这个参数可以没有        #:param r_type: 要查找的关系的类型        #:return:  None 或者 多条查询结果组成的list

        # 组合条件判断,以匹配相关match_one函数,并返回关系        if (nodes is None) and (r_type is None):            res = self.my_graph.match()            return list(res)            #raise TypeError('nodes 和 r_type 必须有一个是非空')        elif (not (nodes is None)) and (not (r_type is None)):            res = self.my_graph.match(nodes=nodes, r_type=r_type)            if res is None:                return None            else:                return list(res)        elif (not (nodes is None)) and (r_type is None):            res = self.my_graph.match(nodes=nodes)            if res is None:                return None            else:                return list(res)        elif (nodes is None) and (not (r_type is None)):            res = self.my_graph.match(r_type=r_type)            if res is None:                return None            else:                return list(res)

    def isExist(self, node=None, relationship=None):        #判断节点和关系是否存在

        #组合条件判断,返回节点和关系是否存在        if (node is None) and (relationship is None):            raise TypeError('要查询的 node 和 relationship 之中必须有一个存在值')        if (not (node is None)) and isinstance(node, Node):            return self.my_graph.exists(node)        elif (not (relationship is None)) and isinstance(relationship, Relationship):            return self.my_graph.exists(relationship)        else:            raise TypeError('要查询的 node 或 relationship 的类型并不是 Node 或 Relationship')

    def deleteall(self):        #删除所有节点        self.my_graph.delete_all()

    def delete(self, node=None, relationship=None):        #根据节点和关系进行删除        # 组合条件判断,返回节点和关系是否存在        if (node is None) and (relationship is None):            raise TypeError('要查询的 node 和 relationship 之中必须有一个存在值')        if (not (node is None)) and isinstance(node, Node):            return self.my_graph.delete(node)        elif (not (relationship is None)) and isinstance(relationship, Relationship):            return self.my_graph.delete(relationship)        else:            raise TypeError('要查询的 node 或 relationship 的类型并不是 Node 或 Relationship')

if __name__ == '__main__':    dao = Neo4jDao(username='neo4j', password='Wbq197711')    dao.deleteall()    node1 = dao.createNode(label='WH',properties={'name': 'test_node_1', 'ip': '10.*.*.1', 'servicename': 'XXX系统'})    node2 = dao.createNode(label='WH',properties={'name': 'test_node_2', 'ip': '10.*.*.2', 'servicename': 'XXX系统'})    node3 = dao.createNode(label='WH',properties={'name': "test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX系统'"})    relation = dao.createRelationship(start_node=node1, end_node=node2, relation_type='VISIT')    relation = dao.createRelationship(start_node=node2, end_node=node1, relation_type='VISIT')    relation = dao.createRelationship(start_node=node1, end_node=node3, relation_type='VISIT')    relation = dao.createRelationship(start_node=node2, end_node=node3, relation_type='VISIT',relation_properties={'port':'8080'})    nodes=dao.findAllNode(node_type='WH')    print(nodes)    #[(_487:WH {ip: '10.*.*.1', name: 'test_node_1', servicename: 'XXX\u7cfb\u7edf'}),    # (_580:WH {name: "test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX\u7cfb\u7edf'"}),    # (_645:WH {ip: '10.*.*.2', name: 'test_node_2', servicename: 'XXX\u7cfb\u7edf'})]    node1=dao.findOneNode(node_type='WH')    print(node1)    #(_487:WH {ip: '10.*.*.1', name: 'test_node_1', servicename: 'XXX\u7cfb\u7edf'})    relations = dao.findAllRelationship()    print(relations)    #[(test_node_1)-[:VISIT {}]->(test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX系统'),    # (test_node_1)-[:VISIT {}]->(test_node_2),    # (test_node_2)-[:VISIT {port: '8080'}]->(test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX系统'),    # (test_node_2)-[:VISIT {}]->(test_node_1)]    relations=dao.findAllRelationship(r_type='VISIT')    print(relations)    #[(test_node_1)-[:VISIT {}]->(test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX系统'),    # (test_node_1)-[:VISIT {}]->(test_node_2),    # (test_node_2)-[:VISIT {port: '8080'}]->(test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX系统'),    # (test_node_2)-[:VISIT {}]->(test_node_1)]    relations = dao.findAllRelationship(nodes=[node1,node2])    print(relations)    #[(test_node_1)-[:VISIT {}]->(test_node_2)]    dao.delete(node1)    node1 = dao.findAllNode(node_type='WH')    print(node1)    #[(_580:WH {name: "test_node_3', 'ip': '10.*.*.3', 'servicename': 'XXX\u7cfb\u7edf'"}),    # (_645:WH {ip: '10.*.*.2', name: 'test_node_2', servicename: 'XXX\u7cfb\u7edf'})]

打开http://127.0.0.1:7474/browser/,运行MATCH (n) RETURN n,即可返回以下图。

后续要完善的:

1、进一步封装,把节点和关系以类的方式封装

2、关于节点和关系的加载,以neo4j和py2neo方式进行加载

3、关于图库的展现问题

4、关于neo4j的高级语法,包括group,sort和计算

王老师的公众号为:追梦IT人,欢迎关注。

近期热文:

迁移到MySQL的业务架构演进实战

数据库修改密码风险高,如何保证业务持续,这几种密码双活方案可以参考

MySQL业务双活的初步设计方案

如何优化MySQL千万级大表,我写了6000字的解读

一道经典的MySQL面试题,答案出现三次反转

业务双活的数据切换思路设计(下)

业务双活的数据切换思路设计(一)

MySQL中的主键和rowid,看似简单,其实有一些使用陷阱需要注意

小白学MySQL要多久?我整理了10多个问题的答案

转载热文:

《吊打面试官》系列-Redis基础

唯一ID生成算法剖析,看看这篇就够了

关于大数据运维能力的一些思考

DBA菜鸟的进化简史:不忘初心,记工作中踩过的三个坑

美女主持直播,被突发意外打断!湾区网友却高喊: 我懂!超甜

QQ群号:763628645

QQ群二维码如下, 添加请注明:姓名+地区+职位,否则不予通过

在看,让更多人看到

图数据库Neo4j学习笔记系列相关推荐

  1. 图数据库 Neo4j 学习总结

    Neo4j是一个NoSQL的图数据库管理系统,这里所说的图是指图论中的图这种数据结构,图是一个比线性表和树更高级的数据结构. Neo4j存储的数据是一个属性图,其中,节点表示一个实体,节点的属性表示实 ...

  2. 图数据库 Dgraph 学习笔记

    Dgraph - an open source, low latency, high throughput, native and distributed graph database. Dgraph ...

  3. SQL Server 2008/2012中SQL应用系列及BI学习笔记系列--目录索引

    SQL Server 2008中的一些特性总结及BI学习笔记系列,欢迎与邀月交流. 3w@live.cn  ◆0.SQL应用系列 1.SQL Server 2008中SQL增强之一:Values新用途 ...

  4. 图数据库Neo4j简介

    图数据库Neo4j简介 转自: 图形数据库Neo4J简介 - loveis715 - 博客园 https://www.cnblogs.com/loveis715/p/5277051.html 最近我在 ...

  5. SQLServer学习笔记系列2

    SQLServer学习笔记系列2 一.写在前面的话 继上一次SQLServer学习笔记系列1http://www.cnblogs.com/liupeng61624/p/4354983.html以后,继 ...

  6. 图数据库Neo4j的介绍与使用

    Neo4j 是一个高性能的 NoSQL 图形数据库,它将结构化数据存储在网络(从数学角度叫做图)上而不是表中.Neo4j 也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性. 接下来我们 ...

  7. 图数据库Neo4j技术原理探秘

    尚学堂给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibili 如前文图数据Neo4j导论所提,Ne ...

  8. Neo4j(1):图数据库Neo4j介绍

    1 什么是图数据库(graph database) 随着社交.电商.金融.零售.物联网等行业的快速发展,现实社会织起了了一张庞大而复杂的关系网,传统数据库很难处理关系运算.大数据行业需要处理的数据之间 ...

  9. 图数据库Neo4j介绍

    1.图数据库Neo4j介绍 1.1 什么是图数据库(graph database) 随着社交.电商.金融.零售.物联网等行业的快速发展,现实社会织起了了一张庞大而复杂的关系网,传统数据库很难处理关系运 ...

最新文章

  1. bzoj:1221;vijos 1552 软件开发
  2. Cylinder3D :3D环境下的Lidar 点云分割
  3. 第五课.高斯判别分析
  4. 【PHPExcel】数学公式
  5. Cocoa touch(十):UIDatePicker
  6. Go的strconv一
  7. 一位资深程序员的成长故事
  8. java+逆向工程怎么运行_MyBatis逆向工程的创建和使用
  9. linux编程学习_您需要编程技能才能学习Linux吗?
  10. 如​何​计​算​当​地​的​中​央​子​午​线​经​度
  11. JSP+MySQL基于ssm的物理竞赛管理系统
  12. 小程序开发时所用到的图标素材 6113个开发小图标
  13. Michael Bronstein从代数拓扑学取经,提出了一种新的图神经网络计算结构!
  14. dw cs5 html,Dreamweaver CS5-HTML简介
  15. 使用Unison 同步文件
  16. Requests 校花网图片爬取
  17. Windows应用程序未响应怎么办文件还没保存呢,是什么原因导致的应用程序未响应?
  18. 微信小程序退款功能(详解完整)
  19. vue入门之04-生命周期 数据共享
  20. C语言(二级基础知识2)

热门文章

  1. js获取光标,设置光标位置
  2. python英译汉库模块_翻译|Python标准功能库1
  3. 苹果系统广讯通服务器,广讯通怎么设置服务器地址
  4. 反向不归零码NRZI
  5. 手机订货软件for android1.5
  6. 如何在线制作GIF视频?怎样将视频转gif格式
  7. python自动部署环境_selenium + python 部署自动化测试环境
  8. JAVA毕业生实习管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
  9. krusal算法无解析(周灵猪)
  10. Symbian 3rd 带参数启动进程