

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 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 大小寫類型名稱和駝峰式大小寫欄位名稱。

## `@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 查詢來解析欄位值、新增查詢或新增變動。例如，這會將新的 `outboundRoutesCount` 欄位新增至 `Airport` 類型，以對傳出路由進行計數：

```
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` 是傳回範圍。

您也可以使用 Gemlin 查詢來新增查詢或變動：

```
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
}
```

目前，Gemlin 查詢限於傳回純量值或 `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` 參數，在此檔案上執行公用程式時，公用程式會立即套用您的變更。