基数与关系建模
|
这是 GraphQL Library 7 版本的文档。对于长期支持 (LTS) 版本 5,请参考 GraphQL Library 5 LTS 版本。 |
无论您的 Neo4j 数据库中有什么样的数据模型,GraphQL 模式的设计都应允许访问您的应用程序所需的数据。这意味着对于数据库中相同类型的数据,通常有多种方式来建模 GraphQL 模式,每种方式都有其优点和权衡。
本页面描述了在 GraphQL 模式中建模 Neo4j 关系的不同方式。
数据模型
以如下图形为例,其中一个 Person 类型具有两种不同的关系类型,可以将它连接到 Movie 类型。
建模关系
数据模型代表了数据库中图形的状态,但在 GraphQL 模式中,有多种方式来建模这些关系。
您在 GraphQL 模式中建模关系的方式会影响您查询和操作数据的方式,因此选择适合您应用程序需求的数据模型非常重要。
下面的类型定义不包含任何关系字段,但作为 GraphQL 模式同样有效,唯一的区别在于它们不允许遍历 Person 节点和 Movie 节点之间的关系。
type Person @node {
name: String!
}
type Movie @node {
title: String!
released: Int!
}
同样,关系不必在关系的两侧都进行建模。虽然数据库中的底层关系必须有源节点和目标节点,但 GraphQL 模式可能只描述关系的一侧。
在以下类型定义中,Movie 可以通过 actors 关系字段访问 Person 节点,但 Person 无法访问 Movie 节点。
type Person @node {
name: String!
}
type Movie @node {
title: String!
released: Int!
actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}
多对多关系
一个 Person 可以出演多部 Movie,而一部 Movie 可以有多个出演其中的 Person。
从概念上讲,这是一个多对多关系,通过在关系两侧的两个关系字段中使用列表类型来建模。
type Person @node {
name: String!
actedIn: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}
type Movie @node {
title: String!
released: Int!
actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}
|
列表类型和列表内部的类型都必须是不可为空的(non-nullable),这意味着关系字段必须始终返回一个值数组,且该数组不能包含空值。这意味着总是存在一定数量的相关节点(即使数量为零),且相关节点始终是有效的节点(从不为空)。 换句话说,数组和数组内部的类型都必须带有 |
一对多关系
一个 Person 可以导演多部 Movie,但一部 Movie 只能有一个导演。
从概念上讲,这是一个一对多关系,通过在 Person 类型的关系字段中使用列表类型,并在 Movie 类型的关系字段中使用非列表类型来建模。
type Person @node {
name: String!
actedIn: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
directed: [Movie!]! @relationship(type: "DIRECTED", direction: OUT)
}
type Movie @node {
title: String!
released: Int!
actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
director: Person @relationship(type: "DIRECTED", direction: IN)
}
|
在关系的“多”侧,列表类型和列表内部的类型必须是不可为空的(参见多对多关系)。这意味着关系字段必须始终返回一个值数组,且该数组不能包含空值。 在关系的“一”侧,类型必须是可为空的,这意味着如果没有相关节点,关系字段可以返回 null。 |
一对一关系
一个人 Person Ana 只能与另一个 Person Bob 结婚,而那个人 Person Bob 也只能与 Person Ana 结婚。
从概念上讲,这是一个一对一关系,通过在关系两侧的关系字段中使用非列表类型来建模。
type Person @node {
name: String!
spouse: Person @relationship(type: "MARRIED", direction: OUT)
}
在这种情况下,关系是相同类型节点之间的关系。这并非必须如此,仅作为本例说明。
|
关系字段类型必须是可为空的,这意味着如果没有相关节点,关系字段可以返回 null。 |
基数
节点类型上的非列表关系字段(一对一或一对多关系中的“一”侧)被称为单一关系字段。
Neo4j 数据库目前不支持关系基数约束,因此如果 API 允许对 单一关系 进行数据操作,用户必须注意数据完整性问题的可能性。