-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Michał Matczuk <[email protected]>
- Loading branch information
Showing
9 changed files
with
747 additions
and
351 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,104 +1,118 @@ | ||
# GoCQLX [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/scylladb/gocqlx) [![Go Report Card](https://goreportcard.com/badge/github.com/scylladb/gocqlx)](https://goreportcard.com/report/github.com/scylladb/gocqlx) [![Build Status](https://travis-ci.org/scylladb/gocqlx.svg?branch=master)](https://travis-ci.org/scylladb/gocqlx) | ||
# 🚀 GocqlX [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/scylladb/gocqlx) [![Go Report Card](https://goreportcard.com/badge/github.com/scylladb/gocqlx)](https://goreportcard.com/report/github.com/scylladb/gocqlx) [![Build Status](https://travis-ci.org/scylladb/gocqlx.svg?branch=master)](https://travis-ci.org/scylladb/gocqlx) | ||
|
||
Package `gocqlx` is an idiomatic extension to `gocql` that provides usability features. With gocqlx you can bind the query parameters from maps and structs, use named query parameters (:identifier) and scan the query results into structs and slices. It comes with a fluent and flexible CQL query builder and a database migrations module. | ||
GocqlX makes working with Scylla easy and error prone without sacrificing performance. | ||
It’s inspired by [Sqlx](https://github.com/jmoiron/sqlx), a tool for working with SQL databases, but it goes beyond what Sqlx provides. | ||
|
||
## Installation | ||
## Features | ||
|
||
go get -u github.com/scylladb/gocqlx | ||
* Binding query parameters from struct fields, map, or both | ||
* Scanning query results into structs based on field names | ||
* Convenient functions for common tasks such as loading a single row into a struct or all rows into a slice (list) of structs | ||
* Making any struct a UDT without implementing marshalling functions | ||
* GocqlX is fast. Its performance is comparable to raw driver. You can find some benchmarks [here](#performance). | ||
|
||
## Features | ||
Subpackages provide additional functionality: | ||
|
||
* Binding query parameters form struct | ||
* Scanning results into struct or slice | ||
* Automated UDT support | ||
* CRUD operations based on table model ([package table](https://github.com/scylladb/gocqlx/blob/master/table)) | ||
* CQL query builder ([package qb](https://github.com/scylladb/gocqlx/blob/master/qb)) | ||
* CRUD operations based on table model ([package table](https://github.com/scylladb/gocqlx/blob/master/table)) | ||
* Database migrations ([package migrate](https://github.com/scylladb/gocqlx/blob/master/migrate)) | ||
* Fast! | ||
|
||
## Training and Scylla University | ||
## Installation | ||
|
||
go get -u github.com/scylladb/gocqlx | ||
|
||
## Getting started | ||
|
||
[Scylla University](https://university.scylladb.com/) includes training material and online courses which will help you become a Scylla NoSQL database expert. | ||
The course [Using Scylla Drivers](https://university.scylladb.com/courses/using-scylla-drivers/) explains how to use drivers in different languages to interact with a Scylla cluster. | ||
The lesson, [Golang and Scylla Part 3](https://university.scylladb.com/courses/using-scylla-drivers/lessons/golang-and-scylla-part-3-gocqlx/) includes a sample application that uses the GoCQXL package. | ||
It connects to a Scylla cluster, displays the contents of a table, inserts and deletes data, and shows the contents of the table after each action. | ||
Courses in [Scylla University](https://university.scylladb.com/) cover a variety of topics dealing with Scylla data modeling, administration, architecture and also covering some basic NoSQL concepts. | ||
Wrap gocql Session: | ||
|
||
## Example | ||
```go | ||
// Create gocql cluster. | ||
cluster := gocql.NewCluster(hosts...) | ||
// Wrap session on creation, gocqlx session embeds gocql.Session pointer. | ||
session, err := gocqlx.WrapSession(cluster.CreateSession()) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
``` | ||
|
||
Specify table model: | ||
|
||
```go | ||
// metadata specifies table name and columns it must be in sync with schema. | ||
var personMetadata = table.Metadata{ | ||
Name: "person", | ||
Columns: []string{"first_name", "last_name", "email"}, | ||
PartKey: []string{"first_name"}, | ||
SortKey: []string{"last_name"}, | ||
} | ||
|
||
// personTable allows for simple CRUD operations based on personMetadata. | ||
var personTable = table.New(personMetadata) | ||
|
||
// Person represents a row in person table. | ||
// Field names are converted to camel case by default, no need to add special tags. | ||
// If you want to disable a field add `db:"-"` tag, it will not be persisted. | ||
type Person struct { | ||
FirstName string | ||
LastName string | ||
Email []string | ||
FirstName string | ||
LastName string | ||
Email []string | ||
} | ||
``` | ||
|
||
// Insert, bind data from struct. | ||
{ | ||
stmt, names := qb.Insert("gocqlx_test.person").Columns("first_name", "last_name", "email").ToCql() | ||
q := gocqlx.Query(session.Query(stmt), names).BindStruct(p) | ||
Bind data from a struct and insert a row: | ||
|
||
if err := q.ExecRelease(); err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
// Get first result into a struct. | ||
{ | ||
var p Person | ||
stmt, names := qb.Select("gocqlx_test.person").Where(qb.Eq("first_name")).ToCql() | ||
q := gocqlx.Query(session.Query(stmt), names).BindMap(qb.M{ | ||
"first_name": "Patricia", | ||
}) | ||
if err := q.GetRelease(&p); err != nil { | ||
t.Fatal(err) | ||
} | ||
```go | ||
p := Person{ | ||
"Michał", | ||
"Matczuk", | ||
[]string{"[email protected]"}, | ||
} | ||
// Load all the results into a slice. | ||
{ | ||
var people []Person | ||
stmt, names := qb.Select("gocqlx_test.person").Where(qb.In("first_name")).ToCql() | ||
q := gocqlx.Query(session.Query(stmt), names).BindMap(qb.M{ | ||
"first_name": []string{"Patricia", "Igy", "Ian"}, | ||
}) | ||
if err := q.SelectRelease(&people); err != nil { | ||
t.Fatal(err) | ||
} | ||
q := session.Query(personTable.Insert()).BindStruct(p) | ||
if err := q.ExecRelease(); err != nil { | ||
t.Fatal(err) | ||
} | ||
``` | ||
|
||
// metadata specifies table name and columns it must be in sync with schema. | ||
var personMetadata = table.Metadata{ | ||
Name: "person", | ||
Columns: []string{"first_name", "last_name", "email"}, | ||
PartKey: []string{"first_name"}, | ||
SortKey: []string{"last_name"}, | ||
Load a single row to a struct: | ||
|
||
```go | ||
p := Person{ | ||
"Michał", | ||
"Matczuk", | ||
nil, // no email | ||
} | ||
q := session.Query(personTable.Get()).BindStruct(p) | ||
if err := q.GetRelease(&p); err != nil { | ||
t.Fatal(err) | ||
} | ||
t.Log(p) | ||
// stdout: {Michał Matczuk [[email protected]]} | ||
``` | ||
|
||
// personTable allows for simple CRUD operations based on personMetadata. | ||
var personTable = table.New(personMetadata) | ||
Load all rows in to a slice: | ||
|
||
// Get by primary key. | ||
{ | ||
p := Person{ | ||
"Patricia", | ||
"Citizen", | ||
nil, // no email | ||
} | ||
stmt, names := personTable.Get() // you can filter columns too | ||
q := gocqlx.Query(session.Query(stmt), names).BindStruct(p) | ||
if err := q.GetRelease(&p); err != nil { | ||
t.Fatal(err) | ||
} | ||
```go | ||
var people []Person | ||
q := session.Query(personTable.Select()).BindMap(qb.M{"first_name": "Michał"}) | ||
if err := q.SelectRelease(&people); err != nil { | ||
t.Fatal(err) | ||
} | ||
t.Log(people) | ||
// stdout: [{Michał Matczuk [[email protected]]}] | ||
``` | ||
|
||
See more examples in [example_test.go](https://github.com/scylladb/gocqlx/blob/master/example_test.go) and [table/example_test.go](https://github.com/scylladb/gocqlx/blob/master/table/example_test.go). | ||
## Examples | ||
|
||
You can find lots of other examples in [example_test.go](https://github.com/scylladb/gocqlx/blob/master/example_test.go), go and run the examples locally: | ||
|
||
```bash | ||
make run-scylla | ||
make run-examples | ||
``` | ||
|
||
## Performance | ||
|
||
With regards to performance `gocqlx` package is comparable to the raw `gocql` baseline. | ||
GocqlX performance is comparable to the raw `gocql` driver. | ||
Below benchmark results running on my laptop. | ||
|
||
``` | ||
|
@@ -110,7 +124,12 @@ BenchmarkBaseGocqlSelect 747 1664365 ns/op 49415 | |
BenchmarkGocqlxSelect 667 1877859 ns/op 42521 B/op 932 allocs/op | ||
``` | ||
|
||
See the benchmark in [benchmark_test.go](https://github.com/scylladb/gocqlx/blob/master/benchmark_test.go). | ||
See the benchmark in [benchmark_test.go](https://github.com/scylladb/gocqlx/blob/master/benchmark_test.go), you can run the benchmark locally: | ||
|
||
```bash | ||
make run-scylla | ||
make bench | ||
``` | ||
|
||
## License | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.