or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
golangpkg:golang/cloud.google.com/go/spanner@v1.87.0

docs

client.mddml.mdindex.mdkeys.mdlow-level.mdprotobuf-types.mdreads.mdtesting.mdtransactions.mdtypes.mdwrites.md
tile.json

tessl/golang-cloud-google-com--go--spanner

tessl install tessl/golang-cloud-google-com--go--spanner@1.87.2

Official Google Cloud Spanner client library for Go providing comprehensive database operations, transactions, and admin functionality

keys.mddocs/

Keys and KeySets

Guide to working with primary keys, key ranges, and key sets for read and delete operations.

Key Type

type Key []interface{}

A Key represents a row's primary key or secondary index key.

Creation:

// Single column key
key := spanner.Key{"alice"}

// Composite key
key := spanner.Key{"alice", 123}

// With typed values
key := spanner.Key{int64(1), "alice", time.Now()}

Supported Types:

int, int8, int16, int32, int64, NullInt64  → INT64
uint8, uint16, uint32                       → INT64
float32, float64, NullFloat64               → FLOAT64
bool, NullBool                              → BOOL
[]byte                                      → BYTES
string, NullString                          → STRING
time.Time, NullTime                         → TIMESTAMP
civil.Date, NullDate                        → DATE
protoreflect.Enum, NullProtoEnum           → ENUM

Key Methods

func (k Key) AsPrefix() KeyRange
func (k Key) String() string

AsPrefix Example:

// Get all rows where key starts with "alice"
key := spanner.Key{"alice"}
keyRange := key.AsPrefix()

iter := client.Single().Read(ctx, "Users", keyRange, columns)

KeyRange Type

type KeyRange struct {
    Start, End Key
    Kind       KeyRangeKind
}

type KeyRangeKind int

const (
    ClosedOpen   KeyRangeKind = iota  // [Start, End)
    ClosedClosed                       // [Start, End]
    OpenClosed                         // (Start, End]
    OpenOpen                           // (Start, End)
)

KeyRange Methods

func (kr KeyRange) String() string

Examples:

// [1, 100) - includes 1, excludes 100
kr := spanner.KeyRange{
    Start: spanner.Key{1},
    End:   spanner.Key{100},
    Kind:  spanner.ClosedOpen,  // Default
}

// [1, 100] - includes both
kr := spanner.KeyRange{
    Start: spanner.Key{1},
    End:   spanner.Key{100},
    Kind:  spanner.ClosedClosed,
}

// Composite key range
kr := spanner.KeyRange{
    Start: spanner.Key{"alice", "2023-01-01"},
    End:   spanner.Key{"alice", "2023-12-31"},
    Kind:  spanner.ClosedClosed,
}

// Prefix range (all keys starting with "alice")
kr := spanner.Key{"alice"}.AsPrefix()

KeySet Interface

type KeySet interface {
    // Has unexported methods
}

func AllKeys() KeySet
func KeySets(keySets ...KeySet) KeySet
func KeySetFromKeys(keys ...Key) KeySet

AllKeys:

// Read all rows
iter := client.Single().Read(ctx, "Users", spanner.AllKeys(), columns)

KeySets - Union of Keys and Ranges:

// Combine multiple keys and ranges
ks := spanner.KeySets(
    spanner.Key{1},
    spanner.Key{5},
    spanner.KeyRange{Start: spanner.Key{10}, End: spanner.Key{20}},
)

iter := client.Single().Read(ctx, "Users", ks, columns)

KeySetFromKeys:

keys := []spanner.Key{
    spanner.Key{1},
    spanner.Key{2},
    spanner.Key{3},
}

ks := spanner.KeySetFromKeys(keys...)
iter := client.Single().Read(ctx, "Users", ks, columns)

Usage Examples

Read Single Row

key := spanner.Key{"alice"}
row, err := client.Single().ReadRow(ctx, "Users", key, []string{"name", "email"})

Read Multiple Specific Rows

keys := spanner.KeySets(
    spanner.Key{"alice"},
    spanner.Key{"bob"},
    spanner.Key{"charlie"},
)

iter := client.Single().Read(ctx, "Users", keys, []string{"name", "email"})

Read Range of Rows

// Users with IDs from 1 to 100
kr := spanner.KeyRange{
    Start: spanner.Key{1},
    End:   spanner.Key{100},
}

iter := client.Single().Read(ctx, "Users", kr, []string{"name", "email"})

Delete with Key

m := spanner.Delete("Users", spanner.Key{"alice"})
_, err := client.Apply(ctx, []*spanner.Mutation{m})

Delete Range

// Delete users 1-99
kr := spanner.KeyRange{
    Start: spanner.Key{1},
    End:   spanner.Key{100},
    Kind:  spanner.ClosedOpen,
}

m := spanner.Delete("Users", kr)
_, err := client.Apply(ctx, []*spanner.Mutation{m})

Delete All

m := spanner.Delete("Users", spanner.AllKeys())
_, err := client.Apply(ctx, []*spanner.Mutation{m})

Composite Keys

Two-Column Key

// Table: UserEvents (UserName STRING, EventDate STRING)
// Primary key: (UserName, EventDate)

// Read single event
key := spanner.Key{"Bob", "2023-09-23"}
row, err := client.Single().ReadRow(ctx, "UserEvents", key, columns)

// Read all events for Bob in 2023
kr := spanner.KeyRange{
    Start: spanner.Key{"Bob", "2023-01-01"},
    End:   spanner.Key{"Bob", "2024-01-01"},
    Kind:  spanner.ClosedOpen,
}
iter := client.Single().Read(ctx, "UserEvents", kr, columns)

Prefix Matching with Composite Keys

// All events for Bob (any date)
key := spanner.Key{"Bob"}
kr := key.AsPrefix()  // Matches all keys starting with "Bob"

iter := client.Single().Read(ctx, "UserEvents", kr, columns)

Descending Keys

For tables with descending keys:

// Table with DESC key: CREATE TABLE T (Key INT64) PRIMARY KEY(Key DESC)

// Range from 100 down to 1 (inclusive)
kr := spanner.KeyRange{
    Start: spanner.Key{100},  // Larger value first
    End:   spanner.Key{1},    // Smaller value second
    Kind:  spanner.ClosedClosed,
}

Best Practices

  1. Use specific keys when possible: More efficient than ranges
  2. Prefer KeyRange over AllKeys: For better performance
  3. Use AsPrefix: For hierarchical key structures
  4. Match key order: Ensure key values match table schema order
  5. Use appropriate Kind: ClosedOpen is usually what you want
  6. Batch key operations: Combine multiple keys with KeySets
  7. Consider key distribution: Avoid hotspots in key design
  8. Use composite keys wisely: Take advantage of prefix matching
  9. Test key ranges: Especially with DESC columns
  10. Document key format: For composite keys in production code