

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 GraphQL 架构的指令
<a name="tools-graphql-schema-with-directives"></a>

您可以从已经有指令的 GraphQL 架构开始，使用如下命令：

```
neptune-for-graphql \
  --input-schema-file {{(your GraphQL schema file with directives)}} \
  --create-update-aws-pipeline \
  --create-update-aws-pipeline-name (name for your new GraphQL API) \
  --create-update-aws-pipeline-neptune-endpoint  {{(empty Neptune database endpoint)}}:{{(port number)}} \
  --output-resolver-query-https
```

您可以修改该实用程序创建的指令，也可以将自己的指令添加到 GraphQL 架构中。以下是一些使用指令的方法：

## 运行该实用程序使其不会生成突变
<a name="tools-graphql-no-mutations"></a>

要防止该实用程序在 GraphQL API 中生成突变，请在 `neptune-for-graphql` 命令中使用 `--output-schema-no-mutations` 选项。

## `@alias` 指令
<a name="tools-graphql-alias-directive"></a>

`@alias` 指令可以应用于 GraphQL 架构类型或字段。它在图形数据库和 GraphQL 架构之间映射不同的名称。语法如下：

```
@alias(property: {{(property name)}})
```

在下面的示例中，`airport` 是映射到 `Airport` GraphQL 类型的图形数据库节点标签，`desc` 是映射到 `description` 字段的图形节点属性（请参阅[航线示例](tools-graphql.md)）：

```
type Airport @alias(property: "airport") {
  city: String
  description: String @alias(property: "desc")
}
```

请注意，标准 GraphQL 格式要求使用 Pascal-casing 类型名称和驼峰大小写的字段名。

## `@relationship` 指令
<a name="tools-graphql-relationship-directive"></a>

`@relationship` 指令将嵌套的 GraphQL 类型映射到图形数据库边缘。语法如下：

```
@relationship(edgeType: {{(edge name)}}, direction: {{(IN or OUT)}})
```

以下是一个示例命令：

```
type Airport @alias(property: "airport") {
  ...
  continentContainsIn: Continent @relationship(edgeType: "contains", direction: IN)
  countryContainsIn: Country @relationship(edgeType: "contains", direction: IN)
  airportRoutesOut(filter: AirportInput, options: Options): [Airport] @relationship(edgeType: "route", direction: OUT)
  airportRoutesIn(filter: AirportInput, options: Options): [Airport] @relationship(edgeType: "route", direction: IN)
}
```

您可以在 [TODO 示例](tools-graphql-start-from-schema.md#tools-graphql-todo-example)和[航线示例](tools-graphql.md)中找到 `@relationship` 指令。

## `@graphQuery` 和 `@cypher` 指令
<a name="tools-graphql-graphquery-cypher-directives"></a>

您可以定义 openCypher 查询来解析字段值、添加查询或添加突变。例如，这将在 `Airport` 类型中添加新的 `outboundRoutesCount` 字段来计算出站路线：

```
type Airport @alias(property: "airport") {
  ...
  outboundRoutesCount: Int @graphQuery(statement: "MATCH (this)-[r:route]->(a) RETURN count(r)")
}
```

以下是新查询和突变的示例：

```
type Query {
  getAirportConnection(fromCode: String!, toCode: String!): Airport \
    @cypher(statement: \
      "MATCH (:airport{code: '$fromCode'})-[:route]->(this:airport)-[:route]->(:airport{code:'$toCode'})")
}

type Mutation {
  createAirport(input: AirportInput!): Airport @graphQuery(statement: "CREATE (this:airport {$input}) RETURN this")
  addRoute(fromAirportCode:String, toAirportCode:String, dist:Int): Route \
    @graphQuery(statement: \
     "MATCH (from:airport{code:'$fromAirportCode'}), (to:airport{code:'$toAirportCode'}) \
      CREATE (from)-[this:route{dist:$dist}]->(to) \
      RETURN this")
}
```

请注意，如果省略 `RETURN`，则解析器会假定关键字 `this` 是返回范围。

也可以使用 Gremlin 查询添加查询或突变：

```
type Query {
  getAirportWithGremlin(code:String): Airport \
    @graphQuery(statement: "g.V().has('airport', 'code', '$code').elementMap()")  # single node
  getAirportsWithGremlin: [Airport] \
    @graphQuery(statement: "g.V().hasLabel('airport').elementMap().fold()")       # list of nodes
  getCountriesCount: Int \
    @graphQuery(statement: "g.V().hasLabel('country').count()")                   # scalar
}
```

目前，Gremlin 查询仅限于返回标量值的查询，或 `elementMap()` 对应于单个节点，或 `elementMap().fold()` 对应于节点列表。

## `@id` 指令
<a name="tools-graphql-id-directive"></a>

`@id` 指令标识映射到 `id` 图形数据库实体的字段。像 Amazon Neptune 这样的图形数据库对于在批量导入期间分配或自动生成的节点和边缘始终具有唯一的 `id`。例如：

```
type Airport {
  _id: ID! @id
  city: String
  code: String
}
```

## 保留类型、查询和突变名称
<a name="tools-graphql-reserved-names"></a>

该实用程序会自动生成查询和突变以创建可正常运行的 GraphQL API。这些名称的模式被解析器识别并保留。以下是类型 `Airport` 和连接类型 `Route` 的示例：

`Options` 类型已保留。

```
input Options {
  limit: Int
}
```

`filter` 和 `options` 函数参数已保留。

```
type Query {
  getNodeAirports(filter: AirportInput, options: Options): [Airport]
}
```

查询名称的 getNode 前缀已保留，诸如 `createNode`、`updateNode`、`deleteNode`、`connectNode`、`deleteNode`、`updateEdge` 和 `deleteEdge` 之类的突变名称的前缀已保留。

```
type Query {
  getNodeAirport(id: ID, filter: AirportInput): Airport
  getNodeAirports(filter: AirportInput): [Airport]
}

type Mutation {
  createNodeAirport(input: AirportInput!): Airport
  updateNodeAirport(id: ID!, input: AirportInput!): Airport
  deleteNodeAirport(id: ID!): Boolean
  connectNodeAirportToNodeAirportEdgeRout(from: ID!, to: ID!, edge: RouteInput!): Route
  updateEdgeRouteFromAirportToAirport(from: ID!, to: ID!, edge: RouteInput!): Route
  deleteEdgeRouteFromAirportToAirport(from: ID!, to: ID!): Boolean
}
```

## 将更改应用于 GraphQL 架构
<a name="tools-graphql-apply-schema-changes"></a>

您可以修改 GraphQL 源架构并再次运行该实用程序，从 Neptune 数据库中获取最新架构。每当该实用程序在数据库中发现新架构时，它都会生成一个新的 GraphQL 架构。

您也可以手动编辑 GraphQL 源架构，然后使用源架构而不是 Neptune 数据库端点作为输入再次运行该实用程序。

最后，您可以使用以下 JSON 格式将更改放入文件中：

```
[
  {
    "type": "{{(GraphQL type name)}}",
    "field": "{{(GraphQL field name)}}",
    "action": "{{(remove or add)}}",
    "value": "{{(value)}}"
  }
]
```

例如：

```
[
  {
    "type": "Airport",
    "field": "outboundRoutesCountAdd",
    "action": "add",
    "value":"outboundRoutesCountAdd: Int @graphQuery(statement: \"MATCH (this)-[r:route]->(a) RETURN count(r)\")"
  },
  {
    "type": "Mutation",
    "field": "deleteNodeVersion",
    "action": "remove",
    "value": ""
  },
  {
    "type": "Mutation",
    "field": "createNodeVersion",
    "action": "remove",
    "value": ""
  }
]
```

然后，当您在命令中使用 `--input-schema-changes-file` 参数对此文件运行该实用程序时，该实用程序会立即应用您的更改。