# 构建图谱

> 本协议支持所有符合RDF规范的图数据库。

将上一章构建出来的RDF数据导入图数据库，即可得到一个简单的社交图。

<figure><img src="/files/XJu8dLZh3ZEhPJhy2AeB" alt=""><figcaption><p>图 7-3 一个简单的社交图</p></figcaption></figure>

## 使用Neptune

> [Amazon Neptune](https://docs.aws.amazon.com/zh_cn/neptune/latest/userguide/intro.html) 是一项快速、可扩展的图形数据库服务。Neptune 可高效存储和导航高度互连的数据。它的查询处理引擎针对领先的图形查询语言 Apache TinkerPop™ Gremlin 和 W3C 的 RDF SPARQL 进行了优化。Neptune 通过这些图形框架开放和标准的 API 实现了高性能。

借助[Amazon Neptune](https://docs.aws.amazon.com/zh_cn/neptune/latest/userguide/intro.html)我们可以把用户在区块链上的行为数据，构建出一个社交图谱。

具体步骤：

1. 在[aws控制台](https://ap-northeast-1.console.aws.amazon.com/neptune/home)启动一个Neptune实例
2. 将上一章构建的sparql拼接成Neptune插入语句：

```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> {
:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe a :Soul;
    p:name "Alice" .
:Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e a :Soul;
    p:name "Bob" .
:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe p:following :Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e .
}}
```

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

```shell
curl -X POST --data-binary '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> {
:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe a :Soul;
    p:name "Alice" .
:Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e a :Soul;
    p:name "Bob" .
:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe p:following :Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e .  }}' https://your-neptune-endpoint:port/sparql
```

至此，我们已经将`Alice follow Bob`的数据索引至图数据库了，通过调用Neptune服务接口查询数据：

```shell
curl -X POST --data-binary 'query=select * where {
?s a :Soul;
  p:name "Alice".
?s p:following ?f .} limit 10' https://your-neptune-endpoint:port/sparql
```

## 使用Jena

为了方便演示，我们使用[docker](https://www.docker.com)来启动一个Jena服务：

```shell
docker run -p 3030:3030 -e ADMIN_PASSWORD=pw123 stain/jena-fuseki
```

启动成功后访问 <http://localhost:3030/，账户：admin/pw123。>

1. 首先创建一个数据集

<figure><img src="/files/uB9FTCi484SL2PjdPkhH" alt=""><figcaption><p>图 7-4 添加一个数据集</p></figcaption></figure>

<figure><img src="https://github.com/relationlabs/relation-docs/blob/gitbook/protocol/zh/indexer/...gitbook/assets/jena-2.png" alt=""><figcaption><p>图 7-5 创建demo数据集</p></figcaption></figure>

2. 然后将上一步的数据导入图数据库

```sparql
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#>

:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe a :Soul;
    p:name "Alice" .

:Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e a :Soul;
    p:name "Bob" .

:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe p:following :Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e .
```

<figure><img src="/files/TPrfFSdl0RdLevbyRPg4" alt=""><figcaption><p>图 7-6 上传RDF数据</p></figcaption></figure>

<figure><img src="/files/qCznkubnY9ioYwrgxZQ9" alt=""><figcaption><p>图 7-7 选择文件并上传</p></figcaption></figure>

3. 最后切换至Query标签页，查询一下Alice关注了哪些人：

```sparql
PREFIX : <http://relationlabs.ai/entity/>
PREFIX p: <http://relationlabs.ai/property/>

SELECT * WHERE {
  ?me a :Soul;
	p:name "Alice";
    p:following ?following .
  ?following p:name ?name .
}
LIMIT 10
```

<figure><img src="/files/esJg6EXeqkpznBKw8Aau" alt=""><figcaption><p>图 7-8 使用SPARQL进行查询</p></figcaption></figure>

<figure><img src="/files/R4hLB0j4E8i3KzkZnRg6" alt=""><figcaption><p>图 7-9 查询结果</p></figcaption></figure>

即可查询到：Alice的地址`0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe` follow了Bob的地址`0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e`。

## 使用Neo4j

为了方便演示，我们使用[docker](https://www.docker.com)来启动一个Neo4j服务：

```shell
docker run \
    -p 7474:7474 -p 7687:7687 \
    --name neo4j-neosemantics \
    neo4j:5.5.0
```

1. 安装插件以支持RDF

```shell
docker exec -it neo4j-neosemantics bash
cd plugins/
wget https://github.com/neo4j-labs/neosemantics/releases/download/5.5.0.0/neosemantics-5.5.0.0.jar
```

2. 配置插件

编辑`conf/neo4j.conf`， 追加配置`dbms.unmanaged_extension_classes=n10s.endpoint=/rdf`。

配置完成后重启Neo4j

```shell
docker restart neo4j-neosemantics
```

Open Neo4j Browser: <http://localhost:7474/browser/> 初始账号：neo4j/neo4j

3. 配置Graph

在Neo4j browser输入框分别执行以下命令：

{% tabs %}
{% tab title="cypher-shell" %}

```cypher
CALL n10s.graphconfig.init();

CREATE CONSTRAINT n10s_unique_uri FOR (r:Resource) REQUIRE r.uri IS UNIQUE;

CALL n10s.graphconfig.init( {  handleMultival: "ARRAY" })

CALL n10s.nsprefixes.add("e", "http://relationlabs.ai/entity/");
CALL n10s.nsprefixes.add("p", "http://relationlabs.ai/property/");
```

{% endtab %}
{% endtabs %}

4. 导入数据

在Neo4j browser中执行以导入数据：

{% tabs %}
{% tab title="cypher-shell" %}

```cypher
CALL n10s.rdf.import.inline("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#>

:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe a :Soul;
    p:name \"Alice\" .

:Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e a :Soul;
    p:name \"Bob\" .

:Soul_0x0109c8ee3151bde7b6b5d9f37e9d2c4bc16930fe p:following :Soul_0x6247123ec0fe0d25feb811e3c4d4a760c1f2e63e .","Turtle");
```

{% endtab %}
{% endtabs %}

5. 查询

在Neo4j browser中查询：

{% tabs %}
{% tab title="cypher-shell" %}

```cypher
MATCH (ss:Resource {p__name: ["Alice"]})-[:p__following]->(oo) RETURN ss, oo
```

{% endtab %}
{% endtabs %}

<figure><img src="/files/YOUpLIzWg2aW59t5Rswg" alt=""><figcaption><p>图 7-10 使用Neo4j</p></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://relationlabs.gitbook.io/protocol/protocol-zh/indexer/build-graph.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
