Skip to content

Go

GreptimeDB uses different client libraries for writing and querying data. You can choose the client library that best suits your needs.

Write data

GreptimeDB provides an ingester library to help you write data. It utilizes the gRPC protocol, which supports schemaless writing and eliminates the need to create tables before writing data. For more information, refer to Automatic Schema Generation.

The Go ingester SDK provided by GreptimeDB is a lightweight, concurrent-safe library that is easy to use with the metric struct.

Installation

Use the following command to install the GreptimeDB client library for Go:

shell
go get -u github.com/GreptimeTeam/greptimedb-ingester-go
go get -u github.com/GreptimeTeam/greptimedb-ingester-go

Import the library in your code:

go
import (
    greptime "github.com/GreptimeTeam/greptimedb-ingester-go"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table/types"
)
import (
    greptime "github.com/GreptimeTeam/greptimedb-ingester-go"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table/types"
)

Connect to database

Username and password are always required to connect to GreptimeDB. For how to set authentication to GreptimeDB, see Authentication. Here we set the username and password when using the library to connect to GreptimeDB.

go
cfg := greptime.NewConfig("127.0.0.1").
    // change the database name to your database name
    WithDatabase("public").
    // Default port 4001
    // WithPort(4001).
    // Enable secure connection if your server is secured by TLS
    // WithInsecure(false).
    // set authentication information
    WithAuth("username", "password")

cli, _ := greptime.NewClient(cfg)
cfg := greptime.NewConfig("127.0.0.1").
    // change the database name to your database name
    WithDatabase("public").
    // Default port 4001
    // WithPort(4001).
    // Enable secure connection if your server is secured by TLS
    // WithInsecure(false).
    // set authentication information
    WithAuth("username", "password")

cli, _ := greptime.NewClient(cfg)

Data model

Each row item in a table consists of three types of columns: Tag, Timestamp, and Field. For more information, see Data Model. The types of column values could be String, Float, Int, Timestamp, etc. For more information, see Data Types.

Low-level API

The GreptimeDB low-level API provides a straightforward method to write data to GreptimeDB by adding rows to the table object with a predefined schema.

Create row objects

This following code snippet begins by constructing a table named cpu_metric, which includes columns host, cpu_user, cpu_sys, and ts. Subsequently, it inserts a single row into the table.

The table consists of three types of columns:

  • Tag: The host column, with values of type String.
  • Field: The cpu_user and cpu_sys columns, with values of type Float.
  • Timestamp: The ts column, with values of type Timestamp.
go
// Construct the table schema for CPU metrics
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // Handle error appropriately
}

// Add a 'Tag' column for host identifiers
cpuMetric.AddTagColumn("host", types.STRING)
// Add a 'Timestamp' column for recording the time of data collection
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
// Add 'Field' columns for user and system CPU usage measurements
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)

// Insert example data
// NOTE: The arguments must be in the same order as the columns in the defined schema: host, ts, cpu_user, cpu_sys
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.11, 0.13)
if err != nil {
    // Handle error appropriately
}
// Construct the table schema for CPU metrics
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // Handle error appropriately
}

// Add a 'Tag' column for host identifiers
cpuMetric.AddTagColumn("host", types.STRING)
// Add a 'Timestamp' column for recording the time of data collection
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
// Add 'Field' columns for user and system CPU usage measurements
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)

// Insert example data
// NOTE: The arguments must be in the same order as the columns in the defined schema: host, ts, cpu_user, cpu_sys
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.11, 0.13)
if err != nil {
    // Handle error appropriately
}

To improve the efficiency of writing data, you can create multiple rows at once to write to GreptimeDB.

go
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // Handle error appropriately
}
cpuMetric.AddTagColumn("host", types.STRING)
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
if err != nil {
    // Handle error appropriately
}

memMetric, err := table.New("mem_metric")
if err != nil {
    // Handle error appropriately
}
memMetric.AddTagColumn("host", types.STRING)
memMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
memMetric.AddFieldColumn("mem_usage", types.FLOAT)
err = memMetric.AddRow("127.0.0.1", time.Now(), 112)
if err != nil {
    // Handle error appropriately
}
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // Handle error appropriately
}
cpuMetric.AddTagColumn("host", types.STRING)
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
if err != nil {
    // Handle error appropriately
}

memMetric, err := table.New("mem_metric")
if err != nil {
    // Handle error appropriately
}
memMetric.AddTagColumn("host", types.STRING)
memMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
memMetric.AddFieldColumn("mem_usage", types.FLOAT)
err = memMetric.AddRow("127.0.0.1", time.Now(), 112)
if err != nil {
    // Handle error appropriately
}

Insert data

The following example shows how to insert rows to tables in GreptimeDB.

go
resp, err := cli.Write(context.Background(), cpuMetric, memMetric)
if err != nil {
    // Handle error appropriately
}
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())
resp, err := cli.Write(context.Background(), cpuMetric, memMetric)
if err != nil {
    // Handle error appropriately
}
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())

Streaming insert

Streaming insert is useful when you want to insert a large amount of data such as importing historical data.

go
err := cli.StreamWrite(context.Background(), cpuMetric, memMetric)
if err != nil {
    // Handle error appropriately
}
err := cli.StreamWrite(context.Background(), cpuMetric, memMetric)
if err != nil {
    // Handle error appropriately
}

Close the stream writing after all data has been written. In general, you do not need to close the stream writing when continuously writing data.

go
affected, err := cli.CloseStream(ctx)
affected, err := cli.CloseStream(ctx)

High-level API

The high-level API uses an ORM style object to write data to GreptimeDB. It allows you to create, insert, and update data in a more object-oriented way, providing developers with a friendlier experience. However, it is not as efficient as the low-level API. This is because the ORM style object may consume more resources and time when converting the objects.

Create row objects

go
type CpuMetric struct {
    Host            string    `greptime:"tag;column:host;type:string"`
    CpuUser         float64   `greptime:"field;column:cpu_user;type:float64"`
    CpuSys          float64   `greptime:"field;column:cpu_sys;type:float64"`
    Ts              time.Time `greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
}

func (CpuMetric) TableName() string {
	return "cpu_metric"
}

cpuMetrics := []CpuMetric{
    {
        Host:        "127.0.0.1",
        CpuUser:     0.10,
        CpuSys:      0.12,
        Ts:          time.Now(),
    }
}
type CpuMetric struct {
    Host            string    `greptime:"tag;column:host;type:string"`
    CpuUser         float64   `greptime:"field;column:cpu_user;type:float64"`
    CpuSys          float64   `greptime:"field;column:cpu_sys;type:float64"`
    Ts              time.Time `greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
}

func (CpuMetric) TableName() string {
	return "cpu_metric"
}

cpuMetrics := []CpuMetric{
    {
        Host:        "127.0.0.1",
        CpuUser:     0.10,
        CpuSys:      0.12,
        Ts:          time.Now(),
    }
}

Insert data

go
resp, err := cli.WriteObject(context.Background(), cpuMetrics)
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())
resp, err := cli.WriteObject(context.Background(), cpuMetrics)
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())

Streaming insert

Streaming insert is useful when you want to insert a large amount of data such as importing historical data.

go
err := cli.StreamWriteObject(context.Background(), cpuMetrics)
err := cli.StreamWriteObject(context.Background(), cpuMetrics)

Close the stream writing after all data has been written. In general, you do not need to close the stream writing when continuously writing data.

go
affected, err := cli.CloseStream(ctx)
affected, err := cli.CloseStream(ctx)

More examples

For fully runnable code snippets and explanations for common methods, see the Examples.

Ingester library reference

Query data

GreptimeDB uses SQL as the main query language and is compatible with MySQL and PostgreSQL. Therefore, we recommend using mature SQL drivers to query data.

We recommend using the GORM library, which is popular and developer-friendly.

Installation

Use the following command to install the GORM library:

shell
go get -u gorm.io/gorm
go get -u gorm.io/gorm

and install the MySQL driver as the example:

shell
go get -u gorm.io/driver/mysql
go get -u gorm.io/driver/mysql

Then import the libraries in your code:

go
import (
    "gorm.io/gorm"
    "gorm.io/driver/mysql"
)
import (
    "gorm.io/gorm"
    "gorm.io/driver/mysql"
)

Connect to database

The following example shows how to connect to GreptimeDB:

go
type Mysql struct {
	Host     string
	Port     string
	User     string
	Password string
	Database string

	DB *gorm.DB
}

m := &Mysql{
    Host:     "127.0.0.1",
    Port:     "4002", // default port for MySQL
    User:     "username",
    Password: "password",
    Database: "public",
}

dsn := fmt.Sprintf("tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
    m.Host, m.Port, m.Database)
dsn = fmt.Sprintf("%s:%s@%s", m.User, m.Password, dsn)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
    //error handling 
}
m.DB = db
type Mysql struct {
	Host     string
	Port     string
	User     string
	Password string
	Database string

	DB *gorm.DB
}

m := &Mysql{
    Host:     "127.0.0.1",
    Port:     "4002", // default port for MySQL
    User:     "username",
    Password: "password",
    Database: "public",
}

dsn := fmt.Sprintf("tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
    m.Host, m.Port, m.Database)
dsn = fmt.Sprintf("%s:%s@%s", m.User, m.Password, dsn)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
    //error handling 
}
m.DB = db

Raw SQL

We recommend you using raw SQL to experience the full features of GreptimeDB. The following example shows how to use raw SQL to query data.

The following code declares a GORM object model:

go
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey"`
    Ts          time.Time `gorm:"column:ts;primaryKey"`
    CpuUser     float64   `gorm:"column:cpu_user"`
    CpuSys      float64   `gorm:"column:cpu_sys"`
}
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey"`
    Ts          time.Time `gorm:"column:ts;primaryKey"`
    CpuUser     float64   `gorm:"column:cpu_user"`
    CpuSys      float64   `gorm:"column:cpu_sys"`
}

If you are using the ORM API to insert data, you can declare the model with both GORM and Greptime tags.

go
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey" greptime:"tag;column:host;type:string"`
    Ts          time.Time `gorm:"column:ts;primaryKey"   greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
    CpuUser     float64   `gorm:"column:cpu_user"        greptime:"field;column:cpu_user;type:float64"`
    CpuSys      float64   `gorm:"column:cpu_sys"         greptime:"field;column:cpu_sys;type:float64"`
}
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey" greptime:"tag;column:host;type:string"`
    Ts          time.Time `gorm:"column:ts;primaryKey"   greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
    CpuUser     float64   `gorm:"column:cpu_user"        greptime:"field;column:cpu_user;type:float64"`
    CpuSys      float64   `gorm:"column:cpu_sys"         greptime:"field;column:cpu_sys;type:float64"`
}

Declare the table name as follows:

go
func (CpuMetric) TableName() string {
	return "cpu_metric"
}
func (CpuMetric) TableName() string {
	return "cpu_metric"
}

Use raw SQL to query data:

go
var cpuMetric CpuMetric
db.Raw("SELECT * FROM cpu_metric LIMIT 10").Scan(&result)
var cpuMetric CpuMetric
db.Raw("SELECT * FROM cpu_metric LIMIT 10").Scan(&result)

Query library reference

For more information about how to use the query library, please see the documentation of the corresponding library:

GORM