> For the complete documentation index, see [llms.txt](https://relationlabs.gitbook.io/semantic-sbt/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://relationlabs.gitbook.io/semantic-sbt/semanticsbt-zh/untitled/shi-yong-the-graph-suo-yin-lian-shang-rdf-shu-ju.md).

# 使用The Graph 索引链上RDF数据

### 概述

在部署Semantic SBT合约后，项目方可以通过对接`The Graph 服务`，来获取链上SBT对应的RDF数据。

在获取到RDF数据后，项目方可以自行选择对应的图数据库来存储从链上的RDF数据。

本文档以AWS的Neptune为例，演示如何将链上RDF数据保存至图数据中。

具体步骤：

1. 通过The Graph获取到数据实体中的RDF数据内容，即链上数据的`turtle数据对象`
2. 通过调用合约的`schemaURI`方法查询RDF对应的数据schema。
3. 将schema和turtle数据对象按SPARQL UPDATE语法格式拼接成对应的图数据库插入语句。
4. 调用Neptune的服务接口

### GraphQL API服务介绍

数据访问方式：

* 通过The Graph 官方提供的webUI(playground)的方式查询
* 通过HTTP请求方式查询
* 通过JS Client的方式查询

#### 数据实体

* id: The transaction id .
* txnHash: The transaction hash in blockchain.
* blockNumber: The block number.
* contract: The contract address.
* owner: The token owner of SBT.
* tokenId: The token id of SBT.
* turtle: The RDF content.

#### Web UI的方式查询

GraphQL API项目地址：

<https://thegraph.com/hosted-service/subgraph/relationlabs/semantic-sbt>

可以登录后可以通过The Graph提供的playground进行查询

<figure><img src="/files/xxjtn78Y0MVVCylsdOQ5" alt=""><figcaption></figcaption></figure>

#### HTTP REST 请求

查询最近两条（对应参数 `first:2`）token对应的数据实体

{% code overflow="wrap" %}

```shell
curl --location --request POST 'https://api.thegraph.com/subgraphs/name/relationlabs/semantic-sbt' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"{\n  turtles(first: 2) {\n    id\n    owner\n    tokenId\n    turtle\n  }\n}"}'
```

{% endcode %}

查询结果

{% code overflow="wrap" %}

```shell
{"data":{"turtles":[{"id":"33456276423","owner":"0x16ff7821a8d293cd2ea07b650fc69ea9206d0615","tokenId":"1","turtle":":Activity1 p:name \"Activity_2049_1\" . :Activity1 p:level 1 . "},{"id":"33456276425","owner":"0x16ff7821a8d293cd2ea07b650fc69ea9206d0615","tokenId":"2","turtle":":Activity2 p:name \"Activity_2049_2\" . :Activity2 p:level 2 . "}]}}
```

{% endcode %}

### 通过JS Client的方式查询

安装 @apollo/client 和 graphql组件

```shell
npm install @apollo/client graphql
```

初始化client

{% code overflow="wrap" %}

```js
import { ApolloClient, InMemoryCache, gql } from '@apollo/client'

const APIURL = 'https://api.thegraph.com/subgraphs/name/relationlabs/semantic-sbt'

const tokensQuery = `
  query($first: Int, $contract: String) {
    turtles(
      first: $first, contract: $contract
    ) {
      id
      tokenId
      owner
      turtle
    }
  }

const client = new ApolloClient({
  uri: APIURL,
  cache: new InMemoryCache(),
})

client
  .query({
    query: gql(tokensQuery),
    variables: {
      first: 2,
      contract: '0xb8eDcD887DF79278E227dAb986cb2a91C2347E02',
    },
  })
  .then((data) => console.log('Subgraph data: ', data))
  .catch((err) => {
    console.log('Error fetching data: ', err)
  })
```

{% endcode %}

### 获取图数据库对应的Schema

通过调用合约的`schemaURI`方法查询schema。

该schema用于构建图数据库时，存储数据时使用。

### RDF数据导入图数据库

1. 在[aws控制台](https://ap-northeast-1.console.aws.amazon.com/neptune/home)启动一个Neptune实例
2. 将turtle数据与对应schema拼接成SPARQL update语句

{% code overflow="wrap" %}

```
update=INSERT DATA 
{ <https://test.com/s> <https://test.com/p> <https://test.com/o> . }
```

{% endcode %}

3\. 调用Neptune服务接口保存RDF数据

{% code overflow="wrap" %}

```shell
curl -X POST --data-binary 'update=INSERT DATA { <https://test.com/s> <https://test.com/p> <https://test.com/o> . }' https://your-neptune-endpoint:port/sparql
```

{% endcode %}

4\. 调用Neptune服务接口查询保存的数据

{% code overflow="wrap" %}

```shell
curl -X POST --data-binary 'query=select ?s ?p ?o where {?s ?p ?o} limit 10' https://your-neptune-endpoint:port/sparql
```

{% endcode %}

### 代码示例

下边通过一段python代码，来示例如何查询链上RDF数据，并保存至Neptune图数据库中的完整过程。

{% code overflow="wrap" %}

```python
import json
import requests

// 通过The graph的HTTP接口，获取链上对应token的RDF数据，并解析对应的turtle数据对象
def graphql_query():
    turtles = []
    graphql_endpoint = 'https://api.thegraph.com/subgraphs/name/relationlabs/semantic-sbt'
    data = {
        'query': '{turtles(where: {contract: "0xb8eDcD887DF79278E227dAb986cb2a91C2347E02", blockNumber_gt: '
                 '"35661923", blockNumber_lt: "35671923"}) {id owner tokenId turtle}} '
    }
    res = requests.post(graphql_endpoint, headers={'Content-Type': 'application/json'}, data=json.dumps(data))
    print(len(json.loads(res.text)['data']['turtles']))
    for item in json.loads(res.text)['data']['turtles']:
        turtles.append(item['turtle'])
    return turtles

// 将turtle数据对象和对应Schema拼装为sparql格式语句，通过Neptune服务接口，保存至图数据库中
def load_rdf(turtles):
    neptune_endpoint = 'https://your-neptune-endpoint:port/sparql'
    for turtle in turtles:
        sparql = 'update=PREFIX : <http://relationlabs.ai/entity/> ' \
                 'PREFIX p: <http://relationlabs.ai/property/> ' \
                 'PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ' \
                 'PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> ' \
                 'PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> ' \
                 'INSERT DATA {GRAPH <http://relationlabs.ai/relationship> { ' + turtle + ' }}'
        res = requests.post(neptune_endpoint,
                            headers={'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'},
                            data=sparql)
        print(res.text)


if __name__ == '__main__':
    load_rdf(graphql_query())
```

{% endcode %}
