技术编程像图一样的数据模型( 二 )


【技术编程像图一样的数据模型】您可以想象将图扩展到还包括有关露西和阿兰或其他人的许多其他的方方面面面 。 例如 , 您可以使用它来表示他们具有的任何食物过敏(通过为每个过敏原引入一个顶点 , 并在人和过敏原之间引入一条边来表示过敏) , 并将这些过敏原与一组顶点相连 , 从而显示出哪些食物中含有哪些物质 。 然后你可以写一个查询到找出每个人食用的安全食品 。 图形具有很好的可扩展性:在向应用程序添加功能时 , 可以轻松扩展图形以适应应用程序数据结构中的更改 。 Cypher查询语言
Cypher是一种属性图的声明式的查询语言 , 是为Neo4j图数据库创建的(它以电影《黑客帝国》中的角色命名 , 而不是与密码学中的密码有关) 。
下列显示了Cypher查询 , 该查询将上图的左手部分插入到图形数据库中 。 图的其余部分可以类似地添加 , 为便于阅读 , 将其省略 。 每个顶点都有一个符号名称 , 例如USA或Idaho , 查询的其他部分可以使用这些名称 , 通过箭头符号在顶点之间创建边:(Idaho)-[:WITHIN]->(USA)创建了标签为WITHIN的边 , 爱达荷州为尾节点 , USA为头节点 。
技术编程像图一样的数据模型
本文插图
当所有的顶点和边都加入到数据库中后 , 我们开始问一些有趣的问题 。 比如说 , 查找所有从美国移民到欧洲的人的名字 。 为了更精确的描述 , 这里我们是想要找出所有:
有BORN_IN标签的指向美国境内位置的边
有LIVES_IN标签的指向欧洲境内位置的边
的顶点 , 然后返回这些顶点的每一个的name属性 。
下图展示了用Cypher是怎么表示这个查询的 。 在MATCH子句中使用相同的箭头符号在图中查找模式:(person)-[:BORN_IN]->() , 匹配由标签为BORN_IN的边相关的任何两个顶点 。 该边的尾顶点绑定到变量person , 而头顶点是未命名 。
技术编程像图一样的数据模型
本文插图
这个查询会按照如下读取:
找出任何一个满足如下两个条件的person顶点:
顶点person有一个往外的 , 指向某个顶点的 , 带有BORN_IN标签的边 。 从那个顶点开始 , 你可以沿着一连串 , 带有WITHIN标签的边 , 最终到达一个类型为Location , 且其name属性为“Unites States"的顶点 。
同一个person顶点 , 有一个往外的带有LIVES_IN标签的边 。 沿着这个边 , 会有一连串的带有WITHIN标签的向外的边 , 并且最终到达一个类型为Location , 且其name属性为“Europe"的顶点 。
对于每一个顶点 , 返回name属性
有好几种可能的方式来执行这个查询 。 这里给描述建议是从扫描所有数据库中的人 , 检索每个人的出生地和居住地 , 然后返回满足条件的人 。
但类似的 , 你也可以从两个Location顶点开始 , 往后查询 。 如果有一个name属性的索引 , 你可能会很高效的找出两个代表US和Europe的顶点 。 然后你可以找出分别通过所有带有往内标签WITHIN的边 , 找出位于美国和欧洲境内的所有位置(包括stats、regions、cities等等) 。 最终 。 你就可以通过一条带有BOIN_IN或LIVES_IN标签的往内(指向一个Location顶点)的边查询到这个人了 。
作为一个典型的声明式语言 , 你在书写查询时不用指定上述的执行细节:查询优化器会自动选择最有效的方式 , 而你可以继续写您的应用程序的其余部分 。 SQL中的图查询
之前我们说过图数据可以用关系行数据库表示 , 但如果我们这么做了 , 我们可以用SQL来查询吗?
答案是可以的 , 但有一些困难 。 在关系型数据库中 , 你通常需要提前知道你要关联哪些你需要的表 。 而在一个图查询中 , 您可能需要遍历可变数量的边 , 才能找到所需的顶点 , 也就是说 , 关联的数量不是预先能确定的 。 在我们的示例中 , 这发生在Cypher查询中 , 发生在()-[:WITHIN*0...]->()里 。 一个带有person顶点的 , 有LIVES_IN标签的边可能指向任何一个位置:street、city、district、region、state等等 。 一个city可能与一个region是WITHIN的关系 , 一个region WITHIN 一个state , 一个state WITHIN 一个country等等 。 带有LIVES_IN标签的边可能直接指向你搜寻位置的顶点 , 或者也有可能经过几个层级才能到达 。


推荐阅读