注:作者的代表作品【Neo4j + D3.js 项目视频教程】http://edu.51cto.com/course/11315.html?reci

Neo4j是什么?

1. Neo4j Web控制台

Neo4j是一个图形数据库,这也就意味着它的数据并非保存在表或集合中,而是保存为节点以及节点之间的关系。在Neo4j中,节点以及关系都能够包含保存值的属性,此外:

  • 可以为节点设置零或多个标签(例如Author或Book)

  • 每个关系都对应一种类型(例如WROTE或FRIEND_OF)

  • 关系总是从一个节点指向另一个节点(但可以在不考虑指向性的情况下进行查询)

为什么要选择Neo4j?

在考虑为web应用选择某个数据库时,我们需要考虑对它有哪些方面的期望,其中最重要的一些条件包括:

  • 它是否易于使用?

  • 它是否允许你方便地回应对需求的变更?

  • 它是否支持高性能查询?

  • 是否能够方便地对其进行数据建模?

  • 它是否支持事务?

  • 它是否支持大规模应用?

  • 它是否足够有趣(很遗憾的是对于数据库的这方面要求经常被忽略)?

从这几个方面来说,Neo4j是一个合适的选择。Neo4j……

  • 自带一套易于学习的查询语言(名为Cypher)

  • 不使用schema,因此可以满足你的任何形式的需求

  • 与关系型数据库相比,对于高度关联的数据(图形数据)的查询快速要快上许多

  • 它的实体与关系结构非常自然地切合人类的直观感受

  • 支持兼容ACID的事务操作

  • 提供了一个高可用性模型,以支持大规模数据量的查询,支持备份、数据局部性以及冗余

  • 提供了一个可视化的查询控制台,你不会对它感到厌倦的

什么时候不应使用Neo4j?

作为一个图形NoSQL数据库,Neo4j提供了大量的功能,但没有什么解决方案是完美的。在以下这些用例中,Neo4j就不是非常适合的选择:

  • 记录大量基于事件的数据(例如日志条目或传感器数据)

  • 对大规模分布式数据进行处理,类似于Hadoop

  • 二进制数据存储

  • 适合于保存在关系型数据库中的结构化数据

在上面的示例中,你看到了由Author、City、Book和Category以及它们之间的关系所组成的一个图形。如果你希望通过Cypher语句在Neo4j web控制台中列出这些数据结果,可以执行以下语句:

MATCH(city:City)<-[:LIVES_IN]-(:Author)-[:WROTE]->(book:Book)-[:HAS_CATEGORY]->(category:Category)WHERE city.name = “Chicago”RETURN *

请注意这种ASCII风格的语法,它在括号内表示节点名称,并用箭头表示一个节点指向另一个节点的关系。Cypher通过这种方式允许你匹配某个指定的子图形模式。

当然,Neo4j的功能不仅仅在于展示漂亮的图片。如果你希望按照作者所处的地点(城市)计算书籍的分类数目,你可以通过使用相同的MATCH模式,返回一组不同的列,例如:

MATCH(city:City)<-[:LIVES_IN]-(:Author)-[:WROTE]->(book:Book)-[:HAS_CATEGORY]->(category:Category)RETURN city.name, category.name, COUNT(book)

执行这条语句将返回以下结果:

city.name

category.name

COUNT(category)

Chicago

Fantasy

1

Chicago

Non-Fiction

2

虽然Neo4j也能够处理“大数据”,但它毕竟不是Hadoop、HBase或Cassandra,通常来说不会在Neo4j数据库中直接处理海量数据(以PB为单位)的分析。但如果你乐于提供关于某个实体及其相邻数据关系(比如你可以提供一个web页面或某个API返回其结果),那么它是一种良好的选择。无论是简单的CRUD访问,或是复杂的、深度嵌套的资源视图都能够胜任。

你应该选择哪种技术栈以配合Neo4j?

所有主流的编程语言都通过HTTP API的方式支持Neo4j,或者采用基本的HTTP类库,或是通过某些原生的类库提供更高层的抽象。此外,由于Neo4j是以Java语言编写的,因此所有包含JVM接口的语言都能够充分利用Neo4j中的高性能API。

Neo4j本身也提供了一个“技术栈”,它允许你选择不同的访问方式,包括简单访问乃至原生性能等等。它提供的特性包括:

  • 通过一个HTTP API执行Cypher查询,并获取JSON格式的结果

  • 一种“非托管扩展”机制,允许你为Neo4j数据库编写自己的终结点

  • 通过一个高层Java API指定节点与关系的遍历

  • 通过一个低层的批量加载API处理海量初始数据的获取

  • 通过一个核心Java API直接访问节点与关系,以获得最大的性能

一个应用程序示例

最近我正好有机会将一个项目扩展为基于Neo4j的应用程序。该应用程序(可以访问graphgist.neo4j.com查看)是关于GraphGist的一个门户网站。GraphGist是一种通过交互式地渲染(在你的浏览器中)生成的文档,它基于一个简单的文本文件(AsciiDoctor),其中用文字描述以及图片描述了整个数据模型、架构以及用例查询,可以在线执行它们,并使它们保持可视化。它非常类似一个iPython notebook或是一张交互式的白纸。GraphGist也允许读者在浏览器中编写自己定义的查询,以查看整个数据集。

Neo4j的原作者Neo Technology希望为GraphGist提供一个由社区创建的展示项目。当然,后端技术选用了Neo4j,而整个技术栈的其余部分,我的选择是:

  • Node.js配合Express.js,其中引入了neo4j包

  • Angular.js

  • Swagger UI

所有代码都已开源,可以在GitHub上任意浏览。

从概念上讲,GraphGist门户网站是一个简单的应用,它提供了一个GraphGist列表,允许用户查看每个GraphGist的详细内容。数据领域是由Gist、Keyword/Domain/Use Case(作为Gist分类)以及Person(作为Gist的作者)所组成的:

现在你已经熟悉这个模型了,在继续深入学习之前,我想为你快速地介绍一下Cypher这门查询语言。举例来说,如果我们需要返回所有的Gist和它们的关键字,可以通过以下语句实现:

MATCH (gist:Gist)-[:HAS_KEYWORD]->(keyword:Keyword)
RETURN gist.title, keyword.name

这段语句将返回一张表,其中的每一行是由每个Gist和Keyword的组合构成的,正如同SQL join的行为一样。现在我们更深入一步,假设我们想要找到某个人所编写的Gist对应的所有Domain,我们可以执行下面这条查询语句:

MATCH (person:Person)-[:WRITER_OF]->(gist:Gist)-[:HAS_DOMAIN]->(domain:Domain)
WHERE person.name = “John Doe”
RETURN domain.name, COUNT(gist)

该语句将返回另一个结果表,其中的每一行包含Domain的名称,以及这个Person对于这一Domain所编写的全部Gist的数量。这里无需使用GROUP BY语句,因为当我们使用例如COUNT()这样的聚合函数时,Neo4j会自动在RETURN语句中对其它列进行分组操作。

现在你对Cypher已经有一点感觉了吧?那么让我们来看一个来自实际应用中的查询。在创建这个门户时,如果能够通过某种方式,只需对数据库进行一次请求就能够返回我们所需的所有数据,并且以一种我们需要的格式进行结构组织,那将十分有用。

让我们开始创建这个用于门户的API(可以在GitHub上找到)的查询吧。首先,我们需要按照Gist的title属性进行匹配,并匹配所有相关的Gist节点:

// Match Gists based on titleMATCH (gist:Gist) WHERE gist.title =~ {search_query}// Optionally match Gists with the same keyword// and pass on these related Gists with the// most common keywords firstOPTIONAL MATCH (gist)-[:HAS_KEYWORD]->(keyword)<-[:HAS_KEYWORD]-(related_gist)

这里有几个要注意的地方。首先,WHERE语句是通过一个正则表达式(即=~操作符)和一个参数对title属性进行匹配的。参数(Parameter)是Neo4j的一项特性,它能够将查询与其所代表的数据进行分离。使用参数能够让Neo4j对查询和查询计划进行缓存,这也意味着你无需担心遭遇查询注入***。其次,我们在这里使用了一个OPTIONAL MATCH语句,它表示我们希望始终返回原始的Gist,即使它并没有相关的Gist。

现在让我们对之前的查询进行扩展,将RETURN语句替换为WITH语句:

MATCH (gist:Gist) WHERE gist.title =~ {search_query}OPTIONAL MATCH (gist)-[:HAS_KEYWORD]->(keyword)<-[:HAS_KEYWORD]-(related_gist)WITH gist, related_gist, COUNT(DISTINCT keyword.name) AS keyword_countORDER BY keyword_count DESCRETURNgist,COLLECT(DISTINCT {related: { id: related_gist.id, title:
related_gist.title, poster_p_w_picpath: related_gist.poster_p_w_picpath, url:
related_gist.url }, weight: keyword_count }) AS related

RETURN语句中的COLLECT()作用是将由Gist和相关Gist所组成的节点转换为一个结果集,让其中每一行Gist只出现一次,并对应一个相关Gist的节点数组。在COLLECT()语句中,我们在相关Gist中仅指定了所需的部分数据,以减小整个响应的大小。

最后,我们将产生这样一条查询语句,这也是最后一次使用WITH语句了:

MATCH (gist:Gist) WHERE gist.title =~ {search_query}OPTIONAL MATCH (gist)-[:HAS_KEYWORD]->(keyword)<-[:HAS_KEYWORD]-(related_gist)WITH gist, related_gist, COUNT(DISTINCT keyword.name) AS keyword_countORDER BY keyword_count DESCWITHgist,COLLECT(DISTINCT {related: { id: related_gist.id, title: related_gist.title, poster_p_w_picpath: related_gist.poster_p_w_picpath, url: related_gist.url }, weight: keyword_count }) AS related// Optionally match domains, use cases, writers, and keywords for each GistOPTIONAL MATCH (gist)-[:HAS_DOMAIN]->(domain:Domain)OPTIONAL MATCH (gist)-[:HAS_USECASE]->(usecase:UseCase)OPTIONAL MATCH (gist)<-[:WRITER_OF]-(writer:Person)OPTIONAL MATCH (gist)-[:HAS_KEYWORD]->(keyword:Keyword)// Return one Gist per row with arrays of domains, use cases, writers, and keywordsRETURNgist,related,COLLECT(DISTINCT domain.name) AS domains,COLLECT(DISTINCT usecase.name) AS usecases,COLLECT(DISTINCT keyword.name) AS keywordsCOLLECT(DISTINCT writer.name) AS writers,ORDER BY gist.title

在这个查询中,我们将选择性地匹配所有相关的Domain、Use Case、Keyword和Person节点,并且将它们全部收集起来,与我们对相关Gist的处理方式相同。现在我们的结果不再是平坦的、反正规化的,而是包含一列Gist,其中每个Gist都对应着相关Gist的数组,形成了一种“has many”的关系,并且没有任何重复数据。太酷了!

不仅如此,如果你觉得用表的形式返回数据太老土,那么Cypher也可以返回对象:

RETURN{
gist: gist,domains: collect(DISTINCT domain.name) AS domains,usecases: collect(DISTINCT usecase.name) AS usecases,writers: collect(DISTINCT writer.name) AS writers,keywords: collect(DISTINCT keyword.name) AS keywords,related_gists: related}ORDER BY gist.title

通常来说,在稍具规模的web应用程序中,需要进行大量的数据库调用以返回HTTP响应所需的数据。虽然你可以并行地执行查询,但通常来说你需要首先返回某个查询的结果集,才能发送另一个数据库请求以获取相关的数据。在SQL中,你可以通过生成复杂的、开销很大的表join语句,通过一个查询从多张表中返回结果。但只要你在同一个查询中进行了多次SQL join,这个查询的复杂性将会飞快地增长。更不用说数据库仍然需要进行表或索引扫描才能够获得相应的数据了。而在Neo4j中,通过关系获取实体的方式是直接使用对应于相关节点的指针,因此服务器可以随意进行遍历。

转载于:https://blog.51cto.com/cloudy/1976777

图数据库Neo4j全栈Web技术解密相关推荐

  1. 天津web前端培训,2022年zui新全栈开发技术有这些

    互联网的飞快发展,带着编程行业技术也在不断更新.到了2022年web前端技术子然也有许多更新.那么在2022年掌握哪些web必会技术才能跟的上时代???今天诚筑说的小编就带大家了解zui新全栈开发技术 ...

  2. 面向全栈的技术管理(多图)

    3月25日周六,在中生代和飞马网的技术嘉年华上,斗胆披上吹牛的嫌疑,分享了面向全栈的技术管理,现赘述如下. 研发管理有着广义和狭义的定义,总的来说,研发管理就是在研发体系基础之上,借助信息平台进行的团 ...

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

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

  4. 从零开始开发一个全栈Web应用实录

    虽说学习了大半年前端,但是对前端的理解仍然停留在对HTML,CSS,JS,JQuery的概念理解上,并且没有接触过相关的后端开发,所以说,这个项目也可称为从零开始,是新手向的文章,不要害怕有门槛哈. ...

  5. 图数据库Neo4j简介

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

  6. 大数据时代的新型数据库 — 图数据库 Neo4j 的应用

    概览 微云数聚(北京)科技有限公司是一家实力雄厚的大数据技术公司,由移动互联网技术专家团队.大数据专业团队和建模博士团队组成.微云数聚专注于研究图数据库技术及其应用,是世界领先的图数据库Neo4j在中 ...

  7. 我的第一个全栈 Web 应用程序

    在这篇文章,作者将使用 React.js 和 Redux.js 前端技术,并通过调用 Ruby on Rails API,手把手教会你如何创建一个完美的全栈 Web 应用程序. 作者 | Anne-L ...

  8. C#语言入门、xamarin基础、.NET MAUI全栈开发技术综合笔记

    文章目录 前言: 一.C#语言入门 1.类 类的三大成员 属性(Property) 方法(Method) 事件(Event) 2.静态成员与实例成员 3.类型.变量和方法 3.1类型(Type) 3. ...

  9. 大数据时代的新型数据库-图数据库Neo4j介绍

    2019独角兽企业重金招聘Python工程师标准>>> 1.Neo4j简介 Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上形成图谱而不是表中.Neo4j也 ...

最新文章

  1. 代码逻辑是分方法写好 还是在一个方法写好_这一团糟的代码,真的是我写的吗?...
  2. java中graphics抽象类_Java中的抽象类
  3. 7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)...
  4. android输入时背景颜色,Button根据EditText输入状态改变背景颜色
  5. HTML如何添加锚点,我先收藏为敬
  6. git学习(9):git 添加 ssh keys 出现如下错误
  7. LeetCode-236: 二叉树的最近公共祖先
  8. oracle apache服务占用80端口
  9. Ceph添加、删除osd及故障硬盘更换
  10. 9011,9012,9013,9014,8050,8550 三极管的区别
  11. iOS切换根控制器动画!
  12. c语言else if函数的使用方法,excel if函数怎么用?excel中if函数的使用方法图文详解...
  13. py交易----实验吧
  14. 【电脑配置】三、解决ubuntu16.04系统无法连接wifi的错误
  15. Nginx访问控制,限速limit_conn, limit_req
  16. 2022年安全员-B证理论题库及模拟考试
  17. 【利用Altium Designer2018设计元器件原理图库】
  18. 【从0到1搭建LoRa物联网】7、国产LoRa终端ASR6505驱动段式LCD例程
  19. 交通运输跨考计算机,有关跨专业考研的一些问题
  20. Vue中使用file类型input标签,无法使用reset方法清空已经选择的文件【简单粗暴的解决方案】

热门文章

  1. PHP垃圾回收机制防止内存溢出
  2. Gym - 100625E Encoded Coordinates 矩阵快速幂
  3. 图解ecshop之批量上传与批量处理
  4. 使用 document.onreadystatechange()来判断页面加载完
  5. python算法很难吗_python 机器学习难吗?
  6. Win64 驱动内核编程-28.枚举消息钩子
  7. POJ2118基础矩阵快速幂
  8. hdu4400 BFS+STL
  9. JavaScript数组方法大全解
  10. github报错“remote: Support for password authentication was removed on August 13, 2021. Please use a p”