Skip to Content
DocumentationFeaturesSecondary Indexes

Secondary Indexes

Oxia allows records to be indexed by one or more secondary keys in addition to their primary key. Secondary indexes enable efficient lookups and range queries on alternative key spaces without duplicating data.

Use cases

  • Multi-attribute lookups: A record keyed by ID can also be indexed by name, email, or any other attribute.
  • Reverse mappings: Create bidirectional lookups without maintaining separate records.
  • Alternative sort orders: Query the same data set using different key orderings.

How secondary indexes work

When writing a record, you can attach one or more secondary index entries. Each entry specifies an index name and a secondary key. The secondary key does not need to be unique — multiple records can share the same secondary key within the same index.

When querying with List, RangeScan, or Get, you can specify an index name to search by secondary keys instead of primary keys. The results still return the primary keys and values of the matching records.

Using secondary indexes

Writing records with secondary indexes

// Index a user record by email _, _, err := client.Put(context.Background(), "/users/123", []byte(`{"name":"Alice","email":"alice@example.com"}`), oxia.SecondaryIndex("by-email", "alice@example.com"), )

Querying by secondary index

Use the UseIndex option on Get, List, or RangeScan to query using secondary keys.

// Lookup by secondary index key, value, version, err := client.Get(context.Background(), "alice@example.com", oxia.UseIndex("by-email"), ) // List all keys in a secondary index range keys, err := client.List(context.Background(), "a", "b", oxia.UseIndex("by-email"), ) // Range scan using secondary index ch := client.RangeScan(context.Background(), "a", "b", oxia.UseIndex("by-email"), ) for result := range ch { fmt.Printf("primary key: %s, value: %s\n", result.Key, string(result.Value)) }

Updating secondary indexes

Secondary indexes are updated atomically with the record. When you Put a record with new secondary index entries, the previous index entries for that record are replaced.

// Update the email index for user 123 _, _, err := client.Put(context.Background(), "/users/123", []byte(`{"name":"Alice","email":"newalice@example.com"}`), oxia.SecondaryIndex("by-email", "newalice@example.com"), )

When a record is deleted, all of its secondary index entries are automatically removed.

Last updated on