QuestDB is a relational column-oriented database designed for time collection and occasion knowledge. It makes use of SQL with extensions for time collection to help with real-time analytics.
If you’re not acquainted sufficient with QuestDB, right here is demo hyperlink to get in contact.
On this tutorial, we are going to construct easy API and implement QuestDB as timeseries database in our undertaking. Then, we are going to use Gin Framework for dealing with HTTP routes.
Earlier than we start, I’ll assume that you simply:
- Have Go put in in your machine
- Perceive the fundamentals of Go language
- Have a common understanding of RESTful API
Operating QuestDB
Firstly, we have to run QuestDB in our native. There are a number of strategies to put in it, you will discover right here. However we are going to use Docker and the most recent questdb Docker picture for comfort.
To start out QuestDB by way of Docker, run the next:
docker run -p 9000:9000
-p 9009:9009
-p 8812:8812
questdb/questdb
Alternatively, macOS customers can use Homebrew:
brew set up questdb
brew companies begin questdb
After beginning QuestDB, the net console is obtainable on port 9000
, so navigating to localhost:9000
ought to present the UI which appears like the next:
Alright, QuestDB is prepared. Now let’s start to the following step.
Constructing a REST API in Go utilizing Gin and Gorm
Let’s begin by initializing a brand new Go module to handle our undertaking’s dependencies.
go mod init
Now let’s set up required dependencies
go get -u github.com/joho/godotenv
go get -u gorm.io/gorm
go get -u github.com/gin-gonic/gin
After set up is full the folder ought to include go.mod
and go.sum
. Each of the information include info of the packages that we have now put in.
For reference, I printed your complete supply code in my github. Be at liberty to clone it.
git clone https://github.com/arifintahu/go-api-questdb
Establishing database
Let’s begin by creating our database connection and fashions.
// fashions/tracker.go
bundle fashions
import (
"time"
)
kind Tracker struct {
Timestamp time.Time `gorm:"kind:timestamp" json:"timestamp"`
VehicleId int `gorm:"kind:int" json:"vehicleId"`
Latitude float64 `gorm:"kind:double" json:"latitude"`
Longitude float64 `gorm:"kind:double" json:"longitude"`
}
We’ve got tracker
fashions that may document each place of autos. Every tracker ought to have a timestamp, a VehicleId with kind of integer, a Latitude and a Longitude with kind of float. We must always contemplate if our varieties can be found in QuestDB varieties or not as said right here.
Subsequent, we are going to create setup perform to connect with our database. We will work together with a QuestDB database by connecting to numerous community endpoints similar to Internet Console, InfluxDB Line Protocol, PostgreSQL Wire Protocol, HTTP REST API.
We are going to use PostgreSQL Wire Protocol by connecting to port 8812
as a result of we will use gorm as ORM in golang. Earlier than that we have to set up gorm driver postgres as a result of we are going to join QuestDB utilizing Postgres driver.
go get -u gorm.io/driver/postgres
Then we are going to write perform for database connection.
// fashions/setup.go
bundle fashions
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var DB *gorm.DB
kind DBConfig struct {
Host string
Consumer string
Password string
Identify string
Port string
}
func (dbConfig *DBConfig) ConnectDatabase() error {
dsn := fmt.Sprintf(
"host=%s person=%s password=%s dbname=%s port=%s",
dbConfig.Host,
dbConfig.Consumer,
dbConfig.Password,
dbConfig.Identify,
dbConfig.Port,
)
database, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
return err
}
database.AutoMigrate(&Tracker{})
DB = database
return nil
}
In setup.go
, we additionally outline auto migration for tracker
mannequin. Subsequently, we need not create desk in our database first.
Writing controllers
Subsequent, we are going to construct easy controllers the place we will create and discover trackers.
// controllers/trackers.go
bundle controllers
import (
"go-api-questdb/fashions"
"internet/http"
"time"
"github.com/gin-gonic/gin"
)
kind CreateTrackerInput struct {
VehicleId int `json:"vehicleId"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
}
func CreateTracker(c *gin.Context) {
var enter CreateTrackerInput
if err:= c.ShouldBindJSON(&enter); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"knowledge": err.Error()})
return
}
tracker := fashions.Tracker{
Timestamp: time.Now().UTC(),
VehicleId: enter.VehicleId,
Latitude: enter.Latitude,
Longitude: enter.Longitude,
}
fashions.DB.Create(&tracker)
c.JSON(http.StatusOK, gin.H{"knowledge": tracker})
}
func GetTrackers(c *gin.Context) {
var trackers []fashions.Tracker
fashions.DB.Discover(&trackers)
c.JSON(http.StatusOK, gin.H{"knowledge": trackers})
}
In trackers controller, we have now CreateTrackerInput
to validate request physique in CreateTracker
handler, then we simply name our DB occasion to execute row creation. We even have GetTrackers
handler to fetch all rows.
RESTful routes
We virtually there!
The very last thing we have to do is creating route handler and software entry level.
// foremost.go
bundle foremost
import (
"go-api-questdb/controllers"
"go-api-questdb/fashions"
"os"
"github.com/gin-gonic/gin"
_ "github.com/joho/godotenv/autoload"
)
func foremost() {
r := gin.Default()
dbConfig := fashions.DBConfig{
Host: os.Getenv("DB_HOST"),
Consumer: os.Getenv("DB_USER"),
Password: os.Getenv("DB_PASSWORD"),
Identify: os.Getenv("DB_NAME"),
Port: os.Getenv("DB_PORT"),
}
err := dbConfig.ConnectDatabase()
if err != nil {
panic(err)
}
r.POST("/trackers", controllers.CreateTracker)
r.GET("/trackers", controllers.GetTrackers)
r.Run("localhost:3000")
}
In foremost.go
, we have now dbConfig
for initializing our database connection and we load our database credentials in .env
file. Subsequently, we have to add .env
file in our undertaking.
We are going to use default person and password of QuestDB as said right here
// .env
DB_HOST=localhost
DB_USER=admin
DB_PASSWORD=quest
DB_NAME=qdb
DB_PORT=8812
Alright, let’s run out API
go run foremost.go
Nice, our app is efficiently operating in localhost:3000
and efficiently migrating new desk.
Let’s check it out by sending POST
request to localhost:3000/trackers
curl --request POST 'localhost:3000/trackers' --header 'Content material-Sort: software/json' --data-raw '{ "vehicleId": 1, "latitude": -7.626923, "longitude": 111.5213978 }'
Then we bought
{
"knowledge": {
"timestamp": "2022-09-09T09:56:01.8970862Z",
"vehicleId": 1,
"latitude": -7.626923,
"longitude": 111.5213978
}
}
Let’s take a look at once more by sending GET
request to localhost:3000/trackers
and we bought
{
"knowledge": [
{
"timestamp": "2022-09-09T09:56:01.8970862Z",
"vehicleId": 1,
"latitude": -7.626923,
"longitude": 111.5213978
}
]
}
Yeay we have now efficiently constructed API with Go and QuestDB 🌟 🌟 🌟