Leveraging a TigerGraph Graph Database with a Web Server in Go for Hackathon Registrations
Creating a Web Server in Golang Using TigerGo and Gin Gonic to Help Hackathon Competitors Find Teammates
Introduction
Amidst the awesome experiences I have had, I am a community leader at Major League Hacks. I enjoy participating in hackathons and I even had the awesome opportunity to host the Texas branch of the Local Hack Day in 2020. One of the potentially difficult but most fun aspects of hackathons is finding teammates that use the same frameworks and have similar interests. So why not leverage the power of graph—specifically TigerGraph—to help hackathon competitors find teammates?
This project will be using the new TigerGraph Go wrapper, TigerGo, with a popular Go webserver package, Gin Gonic, to create a graph-powered webserver to create a hackathon partner-finding application.
Tools Used
- TigerGo: A TigerGraph wrapper (created by me!) for Golang
- TigerGraph Cloud: A platform to create and host TigerGraph graph databases
- Gin Gonic: A popular Golang library to create webservers
Part I: Create a Graph
Step I: Create a New Solution
First, create a new blank solution on TigerGraph Cloud. To do so, navigate to https://tgcloud.io/ and create an account if you do not already have one. Next, navigate to the “My Solutions” tab and press the blue “Create Solution” button.
On the first page, press the “Blank” option then press next.
Do not change anything on the second page; this will set up a free TigerGraph solution. On the third page, configure the options as you would like.
Note: Keep note of the password and subdomain of your solution! Furthermore, the subdomain is unique to other solutions at the time, so you may not be able to use the subdomain in this example.
Verify that everything looks good on the final page then press submit. Next wait for a few minutes till the solution status is a green dot that says “Ready.”
Step II: Open GraphStudio and Import the Solution
Once the solution is ready, open GraphStudio by clicking “GraphStudio” from the dropdown of the four squares (with the hover text of “Applications”).
Note: Next, I will show you how to import my solution directly. If you would rather set up the solution yourself, skip this step but follow the rest. If you would like to import the solution immediately, finish this step, install the query, then jump to Part II.
In GraphStudio, click the “Import an Existing Studio” button.
You can find the solution to import here.
Step III: Create a New Graph and Schema
On the left-hand panel, click “Global View” to open a dropdown. In the dropdown, click “New Graph.” In my case, I will create a graph called “HackGraph.”
Next, press “Design Schema.” Add vertices using the plus sign then create edges. For a step-by-step tutorial on how to create and design schemas using TigerGraph Cloud, check out this video.
For reference, this would be the script equivalent of the graph schema.
CREATE VERTEX Language(PRIMARY_ID language STRING) WITH PRIMARY_ID_AS_ATTRIBUTE="true"
CREATE VERTEX User(PRIMARY_ID user STRING) WITH PRIMARY_ID_AS_ATTRIBUTE="true"
CREATE VERTEX Interest(PRIMARY_ID interest STRING) WITH PRIMARY_ID_AS_ATTRIBUTE="true"CREATE UNDIRECTED EDGE USER_LANGUAGE(FROM User, TO Language, experience STRING)
CREATE UNDIRECTED EDGE USER_INTEREST(FROM User, TO Interest)
Once you have created your schema, press the publish button!
Congrats, you have created your first schema!
Step IV: Write a Query
Next, you need to create the query to actually suggest teammates. Navigate to the “My Queries” tab. Create a new query (which I called “suggestTeammates”).
If you want to learn about GSQL, check out the GSQL 101 documentation. For this, I created a basic query using accumulators. For all of the users sharing a vertex with the user, they receive 1 on the similarity accumulator. In this case, interest and language vertices have the weighting; however, this can be adjusted to give one more or less.
CREATE QUERY suggestTeammates(VERTEX<User> username) FOR GRAPH HackGraph SYNTAX v2 {
SumAccum<INT> @similarity;
Seed = {username};
Res1 = SELECT u FROM Seed:s - (USER_INTEREST:e1) - Interest:i - (USER_INTEREST:e2) - User:u
WHERE u.user != username.user
ACCUM u.@similarity += 1;
Res2 = SELECT u FROM Seed:s - (USER_LANGUAGE:e1) - Language:l - (USER_LANGUAGE:e2) - User:u
WHERE u.user != username.user AND e1.experience == e2.experience
ACCUM u.@similarity += 1;
Users = {User.*};
Res = SELECT u FROM Users:u
WHERE u.user != username.user
ORDER BY u.@similarity DESC
LIMIT 5;
PRINT Res;
}
Finally, install the query.
The solution is ready now! You can now create the Go project.
Part II: Create and Configure a New Golang Project
Step I: Go Get Packages
To start off, initialise a new Golang project.
go mod init test/gin
Next, import gin.
go get -u github.com/gin-gonic/gin
Note: You MUST grab the package with this. Sometimes when running
go mod tidy
, it would throw an error when running the code.
Finally, import TigerGo.
go get github.com/GenericP3rson/TigerGo
Perfect! Everything should be set library-wise.
Step II: Connect to the TigerGraph Solution
Start by creating a file to house the code. For example, I’ll create index.go
. Next, add the quickstart code for TigerGo to the file.
package main import(
"fmt" // fmt for printing stuff out
"github.com/GenericP3rson/TigerGo" // TigerGo
)func main() {
conn := TigerGo.TigerGraphConnection{
Token: "TOKEN",
Host: "https://SUBDOMAIN.i.tgcloud.io",
GraphName: "GRAPHNAME",
Username: "tigergraph",
Password: "PASSWORD"
}
}
If you do not already have a token, leave the field blank and generate one with:
fmt.Println(conn.GetToken())
I would recommend copying the token and password to a separate document and then calling it from the main document.
token.go
package mainfunc token() string {
return "TOKEN_JUST_GENERATED"
}func password() string {
return "PASSWORD"
}
index.go
import(
"fmt"
"github.com/GenericP3rson/TigerGo"
)func main() {
conn := TigerGo.TigerGraphConnection{
Token: token(),
Host: "https://SUBDOMAIN.i.tgcloud.io",
GraphName: "GRAPHNAME",
Username: "tigergraph",
Password: password()
}
}
Fantastic! Test the connection by running conn.Echo()
.
go run .
If all is good, you’re ready to go!
Step III: Create a Gin Server
Now that we can connect to our solution, we can create a basic Gin server, starting with an /echo
endpoint.
package mainimport (
"fmt"
"github.com/GenericP3rson/TigerGo"
"github.com/gin-gonic/gin"
"net/http"
)func main() {
conn := TigerGo.TigerGraphConnection{
Token: token(),
Host: "https://SUBDOMAIN.i.tgcloud.io",
GraphName: "HackGraph",
Username: "tigergraph",
Password: password(),
} r := gin.Default() r.GET("/echo", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": conn.Echo(),
})
}) r.Run(":8080")}
This runs a GET request at the /echo
endpoint. It will return a JSON object of "message": conn.Echo()
(which will be "message": "Hello GSQL"
). Run the files.
go run .
You can ensure everything is working by heading over to http://0.0.0.0:8080/echo/.
Perfect! Once that’s ready, let’s start building out the endpoints for the example!
Part III: Create the Endpoints
For this project, I’ll create four endpoints: /join
, /add-lang
, /add-interest
, and /suggest-teammates
.
Join
When a user joins, we will create a POST request to the server with the parameters of user
.
r.POST("/join", func(c *gin.Context) { usr := c.Query("user")
fmt.Println(conn.UpsertVertex("User", usr, map[string]string{"user": usr}))})
To verify the endpoint works, create a POST request in curl.
curl -X POST http://0.0.0.0:8080/join?user=Username
When running this command, a new Username vertex will be upserted to the database.
Add Interest
The /add-interest
endpoint will function similarly. This time it will upsert two vertices, User and Interest, and upsert an edge to connect the two.
r.POST("/add-interest", func(c *gin.Context) { usr := c.Query("user")
interest := c.Query("interest") fmt.Println(conn.UpsertVertex("User", usr, map[string]string{"user": usr})) fmt.Println(conn.UpsertVertex("Interest", interest, map[string]string{"interest": interest})) fmt.Println(conn.UpsertEdge("User", usr, "USER_INTEREST", "Interest", interest, nil))})
The POST request will then input two parameters: user and interest.
curl -X POST "http://0.0.0.0:8080/add-interest?user=Username&interest=Graph"
Great! This creates a new Graph
vertex and connects it to the Username
vertex previously created.
Add Language
The final POST request the API will make is the /add-lang
request. This will take in three parameters: the user, language, and experience for the edge attribute.
r.POST("/add-lang", func(c *gin.Context) { usr := c.Query("user")
lang := c.Query("lang")
exp := c.Query("experience") fmt.Println(conn.UpsertVertex("User", usr, map[string]string{"user": usr})) fmt.Println(conn.UpsertVertex("Language", lang, map[string]string{"language": lang})) fmt.Println(conn.UpsertEdge("User", usr, "USER_LANGUAGE", "Language", lang, map[string]string{"experience": exp}))})
Once again, query this endpoint using curl.
curl -X POST "http://0.0.0.0:8080/add-lang?user=Username&lang=Go&experience=beginner"
Suggest Teammates
Lastly, we can run a GET request to run the query we wrote in the first step!
r.GET("/suggest-teammates", func(c *gin.Context) { usr := c.Query("user") c.JSON(http.StatusOK, gin.H{
"results": conn.RunInstalledQuery("suggestTeammates", map[string]string{"username": usr}),
})})
Test out the endpoint with curl.
curl -X GET http://0.0.0.0:8080/suggest-teammates?user=Username
Part IV: Next Steps and Resources
Congrats! You have now created a web server in Go querying TigerGraph! Check out the full code here.
Next, you will want to build a website or something else to use the endpoints you created. Additionally, you can add more endpoints to query for more details to make a more complex teammate suggestion algorithm.
If you want to have any questions or would like to work on other cool TigerGraph projects, feel free to join the TigerGraph Discord!
Note: All images, unless otherwise noted, were created by the author.