使用The Graph 索引链上RDF数据

The GraphQL API是Relation基于The Graph开发的链上图数据查询服务

概述

在部署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进行查询

HTTP REST 请求

查询最近两条(对应参数 first:2)token对应的数据实体

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}"}'

查询结果

{"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 . "}]}}

通过JS Client的方式查询

安装 @apollo/client 和 graphql组件

npm install @apollo/client graphql

初始化client

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

获取图数据库对应的Schema

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

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

RDF数据导入图数据库

  1. aws控制台启动一个Neptune实例

  2. 将turtle数据与对应schema拼接成SPARQL update语句

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

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

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

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

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

代码示例

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

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())

Last updated