We have a structure type that implements UnmarshalCQL method. We use it to unmarshal a user defined type. We also want to use the same struct for scanning an entire row. There is StructScan method available in gocqlx for this purpose when iterating over rows, but no equivalent when doing a Select. This commit introduces the possibility when doing select/get as well. Co-authored-by: Michał Matczuk <michal@scylladb.com>
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.
Installation
go get -u github.com/scylladb/gocqlx
Features
- Binding query parameters form struct or map
- Scanning results directly into struct or slice
- CQL query builder (package qb)
- Super simple CRUD operations based on table model (package table)
- Database migrations (package migrate)
- Fast!
Training and Scylla University
Scylla University includes training material and online courses which will help you become a Scylla NoSQL database expert. The course Using Scylla Drivers explains how to use drivers in different languages to interact with a Scylla cluster. The lesson, Golang and Scylla Part 3 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 cover a variety of topics dealing with Scylla data modeling, administration, architecture and also covering some basic NoSQL concepts.
Example
// 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
}
// 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)
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)
}
}
// 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)
}
}
// 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)
// 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)
}
}
See more examples in example_test.go and table/example_test.go.
Performance
With regards to performance gocqlx package is comparable to the raw gocql baseline.
Below benchmark results running on a local machine.
BenchmarkBaseGocqlInsert 1840 586579 ns/op 7803 B/op 39 allocs/op
BenchmarkGocqlxInsert 2107 665080 ns/op 7803 B/op 39 allocs/op
BenchmarkBaseGocqlGet 2124 579242 ns/op 7311 B/op 35 allocs/op
BenchmarkGocqlxGet 2206 529855 ns/op 7647 B/op 38 allocs/op
BenchmarkBaseGocqlSelect 418 3051462 ns/op 49428 B/op 927 allocs/op
BenchmarkGocqlxSelect 357 3492430 ns/op 42632 B/op 933 allocs/op
See the benchmark in benchmark_test.go.
License
Copyright (C) 2017 ScyllaDB
This project is distributed under the Apache 2.0 license. See the LICENSE file for details. It contains software from:
- gocql project, licensed under the BSD license
- sqlx project, licensed under the MIT license
Apache®, Apache Cassandra® are either registered trademarks or trademarks of the Apache Software Foundation in the United States and/or other countries. No endorsement by The Apache Software Foundation is implied by the use of these marks.
GitHub star is always appreciated!