关系

这是 GraphQL Library 7 版本的文档。对于长期支持 (LTS) 版本 5,请参考 GraphQL Library 5 LTS 版本

如果没有关系,你的类型定义只会表示一组相互孤立的节点,几乎没有价值。向数据模型中添加关系可以为数据提供所需的上下文,使其能够在图的广阔范围内运行复杂查询。

本节介绍如何在 GraphQL 架构中建模和操作关系。

数据模型

下面的示例图展示了PersonMovie 类型通过单一关系类型 ACTED_IN 连接。该关系拥有一个属性 roles,用于描述演员在电影中扮演的不同角色。

relationship with properties
图 1. 通过 ACTED_IN 类型关系将 Movie 节点连接到 Person 节点的模型,关系包含 roles 属性。

编写类型定义

节点

要使用 Neo4j GraphQL 库创建上述图,首先一起定义这两个节点类型及其字段。为了让这些类型在图中表示为节点,需要使用@node 指令对其进行装饰。

定义节点类型
type Person @node {
    name: String!
}

type Movie @node {
    title: String!
    released: Int!
}

关系

通过使用@relationship 指令添加特殊的关系字段来定义两种类型之间的关系。

Person 可以参演多部电影,而 Movie 可以拥有多位演员。从概念上看,这是一种多对多关系,你可以在关系的两侧都使用列表类型来建模。

定义关系字段
type Person @node {
    name: String!
    actedInMovies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}

type Movie @node {
    title: String!
    released: Int!
    actors: [Person!]! @relationship(type: "ACTED_IN", direction: IN)
}

关系的解剖结构

关系方向

direction 参数相对于使用 @relationship 指令的节点类型。值 IN 表示关系指向该节点,而 OUT 表示关系从该节点发出。

在示例图中,Person-[ACTED_IN]→Movie 表示类型为 ACTED_IN 的关系指向一个 Movie,因此 Movie.actors 关系字段的 directionIN。相反,Actors.actedInMovies 关系字段的 directionOUT,因为关系从 Person 发出指向 Movie。

要判断 @relationship 指令的 direction 参数应为 IN 还是 OUT,不妨像上图那样将图形可视化,并根据箭头的方向进行建模。

关系属性

ACTED_IN 关系拥有一个属性 roles,用于描述演员在电影中扮演的不同角色。要对其进行建模:

  1. 添加一个使用 @relationshipProperties 指令装饰的 ActedIn 类型,内部包含所需的关系属性。

  2. @relationship 指令的 properties 参数值设为 ActedIn。此设置可以在关系的任一侧或双方进行,取决于你希望从哪里查询关系属性。

定义关系属性
type ActedIn @relationshipProperties {
    roles: [String!]
}

type Person @node {
    name: String!
    actedIn: [Movie!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: OUT)
}

type Movie @node {
    title: String!
    released: Int!
    actors: [Person!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: IN)
}

关系属性字段只能是原始类型或其列表形式。不能使用复杂类型(如对象类型或接口)作为关系属性。