数据库映射

此页面描述了如何使用指令进行数据库映射。您的 GraphQL 类型定义中的每个类型都可以映射到 Neo4j 数据库中的一个实体,例如节点、关系和关系属性。

@relationship

关系通过使用指令标记特定字段来表示——在本例中为 @relationship。它定义了数据库中的关系类型,以及该关系的方向。

要添加第二个节点类型“Actor”并将这两个节点连接在一起,您应该执行以下操作

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

type Actor {
    name: String
    movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}

请注意,在本例中,关系的每个“端”上都有一个指令,但这不是必需的。

@relationshipProperties

定义

"""Required to differentiate between interfaces for relationship properties, and otherwise."""
directive @relationshipProperties on OBJECT

@relationshipProperties 只能用于接口。

用法

为了向关系添加属性,请向您的类型定义中添加一个新的类型,并使用 @relationshipProperties 指令进行装饰。

例如,对于“ACTED_IN”关系,添加一个属性“roles”

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

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

type ActedIn @relationshipProperties {
    roles: [String]
}

请注意,除了此类型之外,在现有的 @relationship 指令中还添加了一个键 properties。有关更多信息,请参阅 类型定义 → 关系

@node

最基本的映射使用 GraphQL 类型名称映射到 Neo4j 节点标签。例如,要表示一个带有标签“Movie”和一个类型为字符串的单个属性“title”的节点

type Movie {
    title: String
}

使用 @node 指令,您可以更好地控制此映射,并且可以指定表示 Neo4j 节点的 GraphQL 对象类型的配置。它可以附加以下可选参数

标签

此参数定义要在 Neo4j 中使用的标签列表,而不是 GraphQL 类型名称

type Dog @node(labels: ["K9"]) {
    name: String!
}

这样,以下查询

{
  dogs {
    name
  }
}

生成 Cypher 查询

MATCH (this: K9)
RETURN this { .name } as name

如果 GraphQL 类型名称仍应用作标签,则也需要指定它。

type Dog @node(labels: ["Dog", "K9"]) {
    name: String!
}

这样,以下查询

{
  dogs {
    name
  }
}

生成 Cypher 查询

MATCH (this:Dog:K9)
RETURN this { .name } as this

定义 labels 意味着您控制节点的数据库标签。Neo4j 中的索引和约束仅支持单个标签,为此使用 labels 参数的第一个元素。

以下示例导致为标签 K9 和属性 name 断言唯一约束

type Dog @node(labels: ["K9", "Dog"]) {
    name: String! @unique
}

使用 $jwt$context

在某些情况下,您可能希望根据请求的用户生成动态标签。为此,您可以使用变量 $jwt 在 JWT 中定义自定义标签

type User @node(labels: ["$jwt.username"]) {
    name: String!
}

以下查询根据用户 JWT 生成不同的 Cypher 查询

{
  users {
    name
  }
}

假设 JWT 中有一个用户,其值为 "username": "arthur",则 Cypher 查询如下所示

MATCH (this:arthur)
RETURN this { .name } as this

类似地,可以直接传递上下文值

type User @node(label: ["$context.appId"]) {
    name: String!
}

使用 Apollo 运行服务器时

const server = new ApolloServer({
    schema: await neoSchema.getSchema(),
});

await startStandaloneServer(server, {
    context: async ({ req }) => ({ req, appId: "myApp" }),
});

@alias

此指令将 GraphQL 字段映射到节点或关系上的 Neo4j 属性。它可以用于任何不是 @cypher@relationship 字段的字段。

例如

type User {
    id: ID! @id @alias(property: "dbId")
    username: String!
}
type User {
    id: ID! @id
    username: String! @alias(property: "dbUserName")
    livesIn: [City!]! @relationship(direction: OUT, type: "LIVES_IN", properties: "UserLivesInProperties")
}

type City {
    name: String
}

type UserLivesInProperties @relationshipProperties {
    since: DateTime @alias(property: "moveInDate")
}
别名中的属性会自动转义(用反引号 `` 括起来),因此无需在它们周围添加转义字符。