The reason why started supporting GraphQL is the Label
used by S2Graph has a strong type system, so it will work well with the schema
provided by GraphQL.
So far, whenever GraphQL schema has been changed, it has been reflected in S2Graph Model (Service, Label... ).
Assume that hbase is running on localhost.
If the hbase environment is not set up, you should type the following commands.
sbt package target/apache-s2graph-0.2.1-SNAPSHOT-incubating-bin/bin/hbase-standalone.sh start
If hbase is running well, run the following command after cloning the project locally.
GraphiQL
is not directly related to the GraphQL
implementation, but is recommended for convenient queries. Because of the license problem, you should download the file through the following command.
cd s2graphql/src/main/resources/assets wget https://raw.githubusercontent.com/daewon/sangria-akka-http-example/master/src/main/resources/assets/graphiql.html
You can see that the graphiql.html
file is added to the s2graphql/src/main/resources/assets
folder as shown below.
$ls graphiql.html
Then let's run http server.
sbt -DschemaCacheTTL=-1 -Dhttp.port=8000 'project s2graphql' '~re-start'
When the server is running, connect to http://localhost:8000
. If it works normally, you can see the following screen.
S2Graph tutorial The following content rewrote Your first graph
to the GraphQL version.
http://localhost:8000
.The environment for this examples is Mac OS and Chrome. You can get help with schema-based Autocompletion
using the ctrl + space
key.
If you add a label
or service
, etc. you will need to refresh
(cmd + r
) your browser because the schema will change dynamically.
The following POST query will create a service named "KakaoFavorites".
Request
mutation { Management { createService( name: "KakaoFavorites" compressionAlgorithm: gz ) { object { name } } } }
Response
{ "data": { "Management": { "createService": { "object": { "name": "KakaoFavorites" } } } } }
The following POST query will create a service column with the age attribute named "user"
Request
mutation { Management { createServiceColumn( serviceName: KakaoFavorites columnName: "user" columnType: string props: { name: "age" dataType: int defaultValue: "0" storeInGlobalIndex: true } ) { isSuccess object { name props { name dataType } } } } }
Response
{ "data": { "Management": { "createServiceColumn": { "isSuccess": true, "object": { "name": "user", "props": [ { "name": "age", "dataType": "int" } ] } } } } }
To make sure the service and service column is created correctly, check out the following.
Since the schema has changed, GraphiQL must recognize the changed schema. To do this, refresh the browser several times.
Request
query { Management { Services(name:KakaoFavorites) { name serviceColumns { name columnType props { name dataType } } } } }
Response
{ "data": { "Management": { "Service": { "name": "KakaoFavorites", "serviceColumns": [ { "name": "user", "columnType": "string", "props": [ { "name": "age", "dataType": "int" } ] } ] } } } }
In S2Graph, relationships are organized as labels. Create a label called friends using the following createLabel API call:
Request
mutation { Management { createLabel( name: "friends" sourceService: { KakaoFavorites: { columnName: user } } targetService: { KakaoFavorites: { columnName: user } } consistencyLevel: strong ) { isSuccess message object { name serviceName tgtColumnName } } } }
Response
{ "data": { "Management": { "createLabel": { "isSuccess": true, "message": "Mutation successful", "object": { "name": "friends", "serviceName": "KakaoFavorites", "tgtColumnName": "user" } } } } }
Check if the label has been created correctly
Since the schema has changed, GraphiQL must recognize the changed schema. To do this, refresh the browser several times.
Request
query { Management { Labels(name: friends) { name srcColumnName tgtColumnName } } }
Response
{ "data": { "Management": { "Label": { "name": "friends", "srcColumnName": "user", "tgtColumnName": "user" } } } }
Now that the label friends is ready, we can store the friendship data. Entries of a label are called edges, and you can add edges with edges/insert API:
Since the schema has changed, GraphiQL must recognize the changed schema. To do this, refresh the browser several times.
Request
mutation { addEdge( friends: [ {from: "Elmo", to: "Big Bird"}, {from: "Elmo", to: "Ernie"}, {from: "Elmo", to: "Bert"}, {from: "Cookie Monster", to: "Grover"}, {from: "Cookie Monster", to: "Kermit"}, {from: "Cookie Monster", to: "Oscar"}, ] ) { isSuccess } }
Response
{ "data": { "addEdge": [ { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true } ] } }
Query friends of Elmo with getEdges API:
Request
query { KakaoFavorites { user(id: "Elmo") { friends { user { id } } } } }
Response
{ "data": { "KakaoFavorites": [ { "friends": [ { "to": "Bert" }, { "to": "Ernie" }, { "to": "Big Bird" } ] } ] } }
Now query friends of Cookie Monster:
Request
query { KakaoFavorites { user(id: "Elmo") { friends { user { id } } } } }
Response
{ "data": { "KakaoFavorites": { "user": [ { "friends": [ { "to": { "id": "Ernie" } }, { "to": { "id": "Big Bird" } }, { "to": { "id": "Bert" } } ] } ] } } }
Before next examples, you should add url to serviceColumn.
Request
mutation { Management { createServiceColumn( serviceName: KakaoFavorites columnName: "url" columnType: string ) { isSuccess object { name } } } }
Response
{ "data": { "Management": { "createServiceColumn": { "isSuccess": true, "object": { "name": "url" } } } } }
Request
mutation { Management { createLabel( name: "post" sourceService: { KakaoFavorites: { columnName: user } } targetService: { KakaoFavorites: { columnName: url } } consistencyLevel: strong ) { isSuccess message object { name } } } }
Response
{ "data": { "Management": { "createLabel": { "isSuccess": true, "message": "Mutation successful", "object": { "name": "post" } } } } }
Now, insert some posts of the users:
Since the schema has changed, GraphiQL must recognize the changed schema. To do this, refresh the browser several times.
Request
mutation { addEdge( post: [ { from: "Big Bird", to: "www.kakaocorp.com/en/main" }, { from: "Big Bird", to: "github.com/kakao/s2graph" }, { from: "Ernie", to: "groups.google.com/forum/#!forum/s2graph" }, { from: "Grover", to: "hbase.apache.org/forum/#!forum/s2graph" }, { from: "Kermit", to: "www.playframework.com"}, { from: "Oscar", to: "www.scala-lang.org"} ] ) { isSuccess } }
Response
{ "data": { "addEdge": [ { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true }, { "isSuccess": true } ] } }
This should be enough for creating the timeline feature! The following two-step query will return the URLs for Elmo's timeline, which are the posts of Elmo's friends:
Request
query { KakaoFavorites { user(id: "Elmo") { id friends { user { id post { url { id } } } } } } }
Response
{ "data": { "KakaoFavorites": { "user": [ { "id": "Elmo", "friends": [ { "user": { "id": "Ernie", "post": [ { "url": { "id": "groups.google.com/forum/#!forum/s2graph" } } ] } }, { "user": { "id": "Bert", "post": [] } }, { "user": { "id": "Big Bird", "post": [ { "url": { "id": "github.com/kakao/s2graph" } }, { "url": { "id": "www.kakaocorp.com/en/main" } } ] } } ] } ] } } }
Also try Cookie Monster's timeline:
Request
query { KakaoFavorites { user(id: "Cookie Monster") { friends { user { id post { url { id } } } } } } }
Response
{ "data": { "KakaoFavorites": { "user": [ { "friends": [ { "user": { "id": "Oscar", "post": [ { "url": { "id": "www.scala-lang.org" } } ] } }, { "user": { "id": "Kermit", "post": [ { "url": { "id": "www.playframework.com" } } ] } }, { "user": { "id": "Grover", "post": [ { "url": { "id": "hbase.apache.org/forum/#!forum/s2graph" } } ] } } ] } ] } } }
The example above is by no means a full blown social network timeline, but it gives you an idea of how to represent, store and query graph data with S2Graph.