目录
1 问题的起源
在Neo4j的1.0阶段时,它只有3个概念,即节点、关系和属性。假设我们创建了一个节点名字叫Joe,同时我们想要描述这个节点是一个人,那么我们可以给这个节点增加一个type属性,取值为person,如图1。这个方案是可行的,因为现在已经可以将此节点与‘Household good’节点和‘geo location’节点区分开来了。
图1
假设现在我们要给Joe划分到一个党派下:左翼、右翼或者中和派,尽管你可以用属性解决这个问题,但你可能会希望更容易的找到给定党派下的所有人。于是你会像图2这样做,把党派当作一个节点,然后创建Joe和党派的关系。
图2
现在你想要做的一件事是让图根据‘person’的唯一标识比如说‘name’,自动地索引‘person’节点。如果你使用的是Cypher,这是不可能的事,因为Neo4j根本分不清‘person’与‘geo location’有什么区别,当一个城市名与人名相同时。同时对于‘Middle-Wing’节点来说,它的连接是非常稠密的,并且仅仅是为了将某一些节点划分到一个集合中。
因此,为了让graph更容易理解,让Cypher更强大,在Neo4j2.0版本中提出了标签这一概念,使得graph能够根据节点的性质索引节点。
在属性图中,一个关系总会有一个type用来描述两个节点是怎么连接的,如图2中的BELONG_TO。标签来源于这个概念的拓展,用来描述整个节点集是如何相关的,这是节点集的分组机制。不用通过添加type属性,而是直接给节点添加两个标签。
图3
2 标签的优点
使用标签可以让你的意图更明显——“这些节点是经常被访问的,并且可以被认为是一个组”。数据库也可以从你明确的意图中获益,因为它现在可以使用这些信息进行操作。
2.1 标签 vs 建立索引的属性
从1.1中可以看出,没有标签之前,属性也可以完成相应的功能,有了标签之后,使得搜索更为方便、简洁和强大。那到底用哪个更好呢?我们以flagged 实体为例来进行测试。在SQL中,你可以为这样的属性创建一列 Boolean 的值,在Neo4j中有两种方式:
- 实体属性具有两种值
- 一个专门的标签
以博客的数据为例:
- User节点,BlogPost节点
- User之间的关系为FOLLOWS
- 对于blog来说有的是drafted有的是published
那么blog有两种组织形式,一种是为已经published的BlogPost节点打上 ActivePost 的标签;另一种是为BlogPost节点创建一个标识属性active,当blog为published时,active='True'。数据的详细组织情况可参考文末链接2。
现在我们要检索出所有已经published的BlogPost节点。可以看到下图两种方式的检索对数据库访问的次数是一致的,都是201次。那是不是说明两种方式差不多呢?
现在我们通过指定的User来再次检索已经published的blog。这次可以看到明显的不同了,使用标签的检索,访问数据库的次数大幅减少,只有58次,而使用属性的访问了170次。可以看出,当我们要检索的节点出现在搜索patterns的末尾时,使用标签性能表现得更好。
tips:
使用match时,避免使用多个标签。如下图,搜索使用了2个标签,同样的事情竟然访问了数据库801次。这是因为Cypher运行了额外的 hasLabel 过滤器。
可以通过使用专门的关系类型来解决这样的问题,比如为他们添加PUBLISHED和DRAFTED关系,然后用关系来找到指定用户的published post。如图所示,用关系来找到指定的节点几乎没有什么代价。所以在设计数据库结构的时候,要根据自己的特定需求来设计属性、标签和关系,以满足自己的搜索需求。
2.2 使用总结
参考链接3中,总结了可以使用的3种情形:
- 使用属性,当你不需要使用类别来进行搜索,只是在返回节点的时候需要用到类别的信息。
- 使用标签,当你需要使用类别来进行搜索时。
- 使用节点+关系,当你需要遍历类别的值,却不知道类别的取值空间时。(本文没有具体提到,就是把ActivePost当成一个节点,再创建blog与此节点的关系)
Reference:
1、https://neo4j.com/blog/nodes-are-people-too/ Nodes are people, too
2、https://graphaware.com/neo4j/2015/01/16/neo4j-graph-model-design-labels-versus-indexed-properties.html Modelling Data in Neo4j: Labels vs. Indexed Properties
3、https://stackoverflow.com/questions/22340475/neo4j-labels-vs-properties-vs-relationship-node neo4j - labels vs properties vs relationship + node