Building a TigerGraph Wrapper
- Blog >
- Building a TigerGraph Wrapper
A Brief Guide on How to Build a Wrapper for TigerGraph for Any Language
Originally featured on Medium by Shreya Chaudhary
What is TigerGraph and Why Build a Wrapper?
TigerGraph is a graph database, and “The Only Scalable Graph Database for the Enterprise.” TigerGraph is a fantastic tool for analysing data, from fraud detection to medical applications. You can get TigerGraph for free at https://www.tigergraph.com/get-tigergraph/.
In the blog, we will create a wrapper for TigerGraph. Building a wrapper allows you to use TigerGraph in your language of choice, and it makes it easier for any other developer to harness the power of TigerGraph.
Overview
To create wrapper, you will need to know how to make GET and POST requests and make with headers. For this blog, we’ll cover how to create a few basic functions:
- Create a Token
- Get Statistics, Echo, etc.
- Read a Vertex, Edge, and Query
- Upsert a Vertex, Edge, and Query
All of these examples are in Javascript.
Part I: Generating a Token
First, we’ll be generating a token. The token will authorise all of the requests. The structure for the request is:
DOMAIN:9000/requesttoken?secret=SECRET&lifetime=LIFETIME
For the SECRET placeholder, you will need to the user create and input a secret. The lifetime is how long the token will last. Finally, the domain is where the graph is hosted. Altogether, in Node.js, the function looked like this:
exports.getToken = (secret, domain = "localhost", lifetime = 1000000, callback = (ans) => { console.log(ans); }) => {
https.get(`https://${domain}:9000/requesttoken?secret=${secret}&lifetime=${lifetime}`, async (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', async () => {
return callback(JSON.parse(data)["token"])
})
});
}
Part II: Getting Started
For all the requests you make, we’ll have similar header settings. I personally put all of this into a class, with a constructor asking for the host, graph name, and token. Almost every request will need the following parameters:
Hostname: The hostname will be the name of wherever the graph is hosted. This usually localhost or DOMAIN_NAME.i.tgcloud.io.
Port: The port should always be 9000; that’s the port for the REST calls.
Path: This will vary based on the method.
Method: Once again, this will vary, though it will either be GET or POST.
Headers: For every request (except a few notable exceptions), you will need a header with an option of “Authorization” assigned to “Bearer YOUR_TOKEN”. Note: YOUR_TOKEN should be replaced with the token you generated.
Altogether, for Node.js, I put everything together like so:
const options = {
hostname: this.HOST,
port: 9000,
path: PATH_NAME, // Path
method: METHOD_TYPE, // Usually either GET or POST
headers: {
'Authorization': `Bearer ${this.TOKEN}`
}
}
Part III: Vertex Data
Reading a Vertex
The read data, we will call a GET request to the graph/vertices endpoint of TigerGraph. To do this, you’ll need to know the user’s graph name and the name of the vertex the user wants to read. Finally, the resulting data will be a JSON object, and you’ll need to read the “results” section.
getVertices(vertex = "_", callback = (ans) => { console.log(ans); }) {const options = {hostname: `${this.HOST}`,port: 9000,path: `/graph/${this.GRAPH}/vertices/${vertex}`,method: 'GET',headers: {'Authorization': `Bearer ${this.TOKEN}`}};const req = https.request(options, res => {console.log(`statusCode: ${res.statusCode}`)let data = '';res.on('data', chunk => {data += chunk;});res.on('end', async () => {if (JSON.parse(data)["error"]) {console.error(JSON.parse(data)["message"]);} else {return callback(JSON.parse(data)["results"]);}});res.on('error', (err) => {console.log(err);})});req.on('error', error => {console.error(error);});req.end();}
Uperting Vertices
Next, upserting vertices are similar, but you’ll need to make a POST request. For this, you’ll call just the graph endpoint. You’ll send the data as JSON object with the following structure:
"vertices": {
"VERTEX_TYPE": {
"VERTEX_ID": {
"ATTRIBUTE_1": "VALUE_1",
"ATTRIBUTE_2": "VALUE_2"
}
}
}
Here’s an example of this on Node.js:
upsertVertex(vertex_type, vertex_id, attributes, callback = (ans) => { console.log(ans); }) {let postData = {};postData["vertices"] = {};postData["vertices"][vertex_type] = {};postData["vertices"][vertex_type][vertex_id] = attributes;postData = JSON.stringify(postData);const options = {hostname: `${this.HOST}`,port: 9000,path: `/graph/${this.GRAPH}`,method: 'POST',headers: {'Authorization': `Bearer ${this.TOKEN}`,'Content-Type': 'application/x-www-form-urlencoded','Content-Length': postData.length}};const req = https.request(options, res => {console.log(`statusCode: ${res.statusCode}`);let data = '';res.on('data', chunk => {data += chunk;});res.on('end', async () => {if (JSON.parse(data)["error"]) {console.error(JSON.parse(data)["message"]);// console.error(data);} else {return callback(data);}});res.on('error', (err) => {console.log(err);})});req.on('error', error => {console.error(error);});req.write(postData);req.end();}
Part IV: Edge Data
Reading an Edge
Reading an edge is a lot like reading a vertex, but you’ll need to input a few more values. First, you’ll need the vertex type and vertex id to get all the edges from a certain value, also with the edge type. Finally, you’ll create a GET request to the graph/edges endpoint to retrieve the data, which once again returns a JSON object with the desirable data being in “results.”
getEdges(vertex_type, vertex_id, edge = "_", callback = (ans) => { console.log(ans); }) {const options = {hostname: `${this.HOST}`,port: 9000,path: `/graph/${this.GRAPH}/edges/${vertex_type}/${vertex_id}/${edge}`,method: 'GET',headers: {'Authorization': `Bearer ${this.TOKEN}`}};const req = https.request(options, res => {console.log(`statusCode: ${res.statusCode}`)let data = '';res.on('data', chunk => {data += chunk;});res.on('end', async () => {if (JSON.parse(data)["error"]) {console.error(JSON.parse(data)["message"]);} else {return callback(JSON.parse(data)["results"]);}});res.on('error', (err) => {console.log(err);})});req.on('error', error => {console.error(error);});req.end();}
Upserting an Edge
Once again, upsert an edge is a lot like upserting a vertex. You will have to make a POST request to the graph endpoint. You’ll need to input which vertices the edge will be connected to, the edge type, and the edge attributes in a JSON format.
Part V: Query Data
Show Processes List
The showProcessesList command is fairly straightforward: it’s a GET request to the /showprocesslist endpoint. This command shows queries which are currently running.
showProcessesList(callback = (ans) => { console.log(ans); }) {const options = {hostname: `${this.HOST}`,port: 9000,path: `/showprocesslist`,method: 'GET',headers: {'Authorization': `Bearer ${this.TOKEN}`}};const req = https.request(options, res => {console.log(`statusCode: ${res.statusCode}`)let data = '';res.on('data', chunk => {data += chunk;});res.on('end', async () => {return callback(JSON.parse(data));});res.on('error', (err) => {console.log(err);})});req.on('error', error => {console.error(error);});req.end();}
Abort Query
The abort query command stops a query, and to do this, makes a GET request to the /abortquery endpoint. For this, you’ll need the request ids of the queries; if you want to abort all of them, simply send an id of “all.”
abortQuery(requestid = ["all"], callback = (ans) => { console.log(ans); }) {const options = {hostname: `${this.HOST}`,port: 9000,path: `/abortquery/${this.GRAPH}?requestid=${requestid.join("&")}`,method: 'GET',headers: {'Authorization': `Bearer ${this.TOKEN}`}};const req = https.request(options, res => {console.log(`statusCode: ${res.statusCode}`)let data = '';res.on('data', chunk => {data += chunk;});res.on('end', async () => {return callback(JSON.parse(data));});res.on('error', (err) => {console.log(err);})});req.on('error', error => {console.error(error);});req.end();}
Run Query
Finally, to run a query, simply call a GET request to the /query endpoint. If the query has parameters, you’ll need to add them at the end of your endpoint with a ?PARAM_1=VAL1&PARAM2=VAL2, and so on.
runQuery(queryname = "MyQuery", parameters = {}, callback = (ans) => { console.log(ans); }) {let endpoints = `/query/${this.GRAPH}/${queryname}`;if (parameters != {}) {endpoints += "?";let c = 0;for (let i in parameters) {// console.log(i);endpoints += `${i}=${parameters[i]}&`;}}endpoints = endpoints.slice(0, -1);// console.log(endpoints);const options = {hostname: `${this.HOST}`,port: 9000,path: endpoints,method: 'GET',headers: {'Authorization': `Bearer ${this.TOKEN}`}};const req = https.request(options, res => {console.log(`statusCode: ${res.statusCode}`)let data = '';res.on('data', chunk => {data += chunk;});res.on('end', async () => {if (JSON.parse(data)["error"]) {console.error(JSON.parse(data)["message"]);} else {return callback(JSON.parse(data)["results"]);}});res.on('error', (err) => {console.log(err);})});req.on('error', error => {console.error(error);});req.end();}
Step VI: Next Steps
Awesome! You’ve now completed the wrapper blog with Node.js examples. If you’re interested in creating your own wrapper for your favourite language, go ahead and do so! So far, the growing list of wrappers include:
- Python
- Javascript
- Swift
- C#
Create your wrapper, and join the TigerGraph Discord to receive support and feedback.