Work with tables
This Astra DB Serverless feature is currently in public preview. Development is ongoing, and the features and functionality are subject to change. Astra DB Serverless, and the use of such, is subject to the DataStax Preview Terms. |
You can use the Data API to create, read, write, and drop tables containing structured data in Serverless (Vector) databases.
Tables are best for use cases where your data is structured and adheres to a pre-defined schema, known as a fixed schema. The database enforces schema compliance when you add or update data.
Whereas collections automatically index all fields, tables don’t have comprehensive automatic indexing. To optimize query performance, you must manually create and manage indexes for your table data. For more information about the role of indexes in tables, see Work with table indexes.
If your data doesn’t have a consistent, enforceable structure or you don’t want to manually manage indexes, consider using dynamic schema collections instead.
In Astra DB, tables reside inside keyspaces in databases. For information about managing databases and keyspaces programmatically, see Databases reference.
With the Data API clients, you use the Database
class to manage tables themselves.
Then, you use the Table
class to work with table data.
Prerequisites
-
Review the prerequisites and other information in Intro to Astra DB APIs.
-
Create a Serverless (Vector) database.
-
The Data API supports collections and tables in Serverless (Vector) databases. This includes semi-structured collections and structured table data that you would otherwise interact with through the CQL shell or a driver.
The Data API does not support Serverless (Non-Vector) databases.
-
Learn how to instantiate a
DataAPIClient
object and connect to your database.
Required client version
The Data API tables commands are available through HTTP and the clients. If you use a client, tables commands are available only in client versions 2.0-preview or later. For more information, see Data API client upgrade guide.
Work with existing CQL tables
For information about working with existing CQL tables through the Data API, including the CQL commands and types that the Data API supports, see Migrate from CQL.
Create a table
Create a new table in a keyspace in a Serverless (Vector) database.
When you create a table, you specify the following:
-
Table name
-
Column names and data types
-
Primary key, which is the unique identifier for the rows in the table
-
Additional table, command, or client-specific settings, which can be optional
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Create a table using a fluent interface for its definition
:
table_definition = (
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.INT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
)
my_table = database.create_table(
"games",
definition=table_definition,
)
Use if_not_exists
to call create_table
without throwing an error if a table with the given name already exists.
In which case, the request silently does nothing.
table_definition = ... # (omitted)
my_table = database.create_table(
"games",
definition=table_definition,
if_not_exists=True,
)
Parameters:
Name | Type | Summary | ||
---|---|---|---|---|
|
|
The name of the table. |
||
|
|
A complete table definition for the table, including the column names, data types, other column settings, and the primary key. This can be an instance of Some types require specific column definitions, particularly maps, lists, sets, and vector columns. For more information about all types, see Column data types. |
||
|
|
This parameter acts a formal specifier for the type checker.
If omitted, the resulting |
||
|
|
The keyspace where the table is to be created. If not specified, the general keyspace setting for the database is used. |
||
|
|
If If
|
||
|
|
A timeout, in milliseconds, to impose on the underlying API request.
If not provided, the |
||
|
|
Optional parameter for tables that have a As an alternative to Astra DB KMS authentication, use Most embedding provider integrations accept a plain |
||
|
|
A complete or partial specification of the APIOptions to override the defaults inherited from the |
Returns:
Table
- A Table object that is typed as Table[dict]
by default.
To provide a more specific type hint, you must pass a row_type
parameter matching the appropriate type hint for the variable used in the assignment.
For more information, see the Example for this command and Typing support.
Example response (reformatted for clarity)
Table(
name="COLLECTION_NAME",
keyspace="default_keyspace",
database.api_endpoint="ASTRA_DB_API_ENDPOINT",
api_options=FullAPIOptions(
token=StaticTokenProvider(APPLICATION_TOKEN),
...
),
...
)
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
# Create a table using the fluent syntax for definition:
from astrapy.constants import SortMode
from astrapy.info import (
CreateTableDefinition,
ColumnType,
)
table_definition = (
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.INT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
)
my_table = database.create_table(
"games",
definition=table_definition,
)
# Create a table with the definition as object:
# (and do not raise an error if the table exists already)
from astrapy.info import (
CreateTableDefinition,
TablePrimaryKeyDescriptor,
TableScalarColumnTypeDescriptor,
TableValuedColumnType,
TableValuedColumnTypeDescriptor,
TableVectorColumnTypeDescriptor,
)
table_definition_1 = CreateTableDefinition(
columns={
"match_id": TableScalarColumnTypeDescriptor(
ColumnType.TEXT,
),
"round": TableScalarColumnTypeDescriptor(
ColumnType.INT,
),
"m_vector": TableVectorColumnTypeDescriptor(
column_type="vector", dimension=3
),
"score": TableScalarColumnTypeDescriptor(
ColumnType.INT,
),
"when": TableScalarColumnTypeDescriptor(
ColumnType.TIMESTAMP,
),
"winner": TableScalarColumnTypeDescriptor(
ColumnType.TEXT,
),
"fighters": TableValuedColumnTypeDescriptor(
column_type=TableValuedColumnType.SET,
value_type=ColumnType.UUID,
),
},
primary_key=TablePrimaryKeyDescriptor(
partition_by=["match_id"],
partition_sort={"round": SortMode.ASCENDING},
),
)
my_table_1 = database.create_table(
"games",
definition=table_definition_1,
if_not_exists=True,
)
# Create a table with the definition as plain dictionary:
# (and do not raise an error if the table exists already)
table_definition_2 = {
"columns": {
"match_id": {"type": "text"},
"round": {"type": "int"},
"m_vector": {"type": "vector", "dimension": 3},
"score": {"type": "int"},
"when": {"type": "timestamp"},
"winner": {"type": "text"},
"fighters": {"type": "set", "valueType": "uuid"},
},
"primaryKey": {
"partitionBy": ["match_id"],
"partitionSort": {"round": 1},
},
}
my_table_2 = database.create_table(
"games",
definition=table_definition_2,
if_not_exists=True,
)
For more information, see the Client reference.
The TypeScript client provides multiple ways to create create tables, depending on your typing preferences and ser/des configuration (if modified). The following strategies and examples focus on typing your tables. For details about other parameters, such as table definitions, see the Parameters and Example for this command.
-
Automatic type inference
-
Manually typed tables
-
Untyped tables
Like Zod or arktype, the Data API TypeScript client can automatically infer the type of the table’s schema.
By default, the client infers TS-equivalent type of the table’s schema from the definition
object that you provide.
There are several ways to extract this type to reuse within your application.
Infer from definition object
To infer the type from the definition
object, you must specify the definition with a <const>
assertion so that TypeScript can infer the exact unwidened type of the object.
Additionally, DataStax strongly recommends using satisfies CreateTableDefinition
for typechecking purposes.
import { CreateTableDefinition, DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db('ENDPOINT', { token: 'TOKEN' });
// Create table schema using bespoke Data API table definition syntax
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
// Infer the TS-equivalent type from the table definition. Equivalent to:
//
// interface TableSchema {
// matchId: string, // Primary key components are not nullable
// round: number,
// score?: number | null, // Non-primary key columns are optional and can return as null
// winner?: string | null,
// when?: DataAPITimestamp | null,
// fighters?: Set<UUID>, // Maps, lists, and sets are optional to insert, but returns as empty instead of null
// mVector?: DataAPIVector | null, // Vectors can be null.
// }
//
// The preceding definition uses some custom types, like DataAPITimestamp, UUID, and DataAPIVector.
// If necessary, you can modify the ser/des logic to use different datatypes instead.
// However, you must provide your own types in that case.
// For more information, see the Typescript client usage documentation.
type TableSchema = InferTableSchema<typeof TableDefinition>;
// Infer the TS-equivalent type of the primary key from the table definition. Equivalent to:
// type TablePK = Pick<TableSchema, 'matchId' | 'round'>;
type TablePK = InferTablePrimaryKey<typeof TableDefinition>;
// Main function
(async function bootstrap() {
// Provide the type explicitly, so TypeScript doesn't have to run any additional typechecking, just to get the same result
const table = await db.createTable<TableSchema, TablePK>('games', { definition: TableDefinition });
// You can then use TableSchema
as you would any other type.
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: TableSchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: { matchId: string, round: number }
const res = await table.insertOne(row);
})();
Infer from created table
For this strategy, you must write the table definition inline or create it with a <const>
assertion.
For an example of <const>
, see Infer from definition object.
import { DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db('ENDPOINT', { token: 'TOKEN' });
// You must put createTable in its own function with no explicit return type annotation.
// This ensures that the type of the table is available from the top-level scope.
//
// If the environment doesn't allow top-level awaits, then you can't call createTable from the top level
// (without creating an unawaited promise) to then extract the type from.
//
// Therefore, you must extract the type from the function itself, and then the function called.
async function mkGamesTable() {
return await db.createTable('games', {
definition: {
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
}
});
}
// Infer the TS-equivalent type from the table definition. Equivalent to:
//
// interface TableSchema {
// matchId: string, // Primary key components are not nullable
// round: number,
// score?: number | null, // Non-primary key columns are optional and can return as null
// winner?: string | null,
// when?: DataAPITimestamp | null,
// fighters?: Set<UUID>, // Maps, lists, and sets are optional to insert, but returns as empty instead of null
// mVector?: DataAPIVector | null, // Vectors can be null.
// }
//
// The preceding definition uses some custom types, like DataAPITimestamp, UUID, and DataAPIVector.
// If necessary, you can modify the ser/des logic to use different datatypes instead.
// However, you must provide your own types in that case.
// For more information, see the Typescript client usage documentation.
type TableSchema = InferTableSchema<typeof mkGamesTable>;
// Infer the TS-equivalent type of the primary key from the table definition. Equivalent to:
// type TablePK = Pick<TableSchema, 'matchId' | 'round'>;
type TablePK = InferTablePrimaryKey<typeof mkGamesTable>;
// Main function
(async function bootstrap() {
// Call the function to actually create the table
const table = await mkGamesTable();
// You can then use TableSchema
as you would any other type.
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: TableSchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: { matchId: string, round: number }
const res = await table.insertOne(row);
})();
Infer from created table with ES2022 top-level await
For this strategy, you must write the table definition inline or create it with a <const>
assertion.
For an example of <const>
, see Infer from definition object.
import { DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db('ENDPOINT', { token: 'TOKEN' });
// You can use this if top-level awaits are allowed in your environment
const table = await db.createTable('games', {
definition: {
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
}
});
// Infer the TS-equivalent type from the table definition. Equivalent to:
//
// interface TableSchema {
// matchId: string, // Primary key components are not nullable
// round: number,
// score?: number | null, // Non-primary key columns are optional and can return as null
// winner?: string | null,
// when?: DataAPITimestamp | null,
// fighters?: Set<UUID>, // Maps, lists, and sets are optional to insert, but returns as empty instead of null
// mVector?: DataAPIVector | null, // Vectors can be null.
// }
//
// The preceding definition uses some custom types, like DataAPITimestamp, UUID, and DataAPIVector.
// If necessary, you can modify the ser/des logic to use different datatypes instead.
// However, you must provide your own types in that case.
// For more information, see the Typescript client usage documentation.
type TableSchema = InferTableSchema<typeof table>;
// Infer the TS-equivalent type of the primary key from the table definition. Equivalent to:
// type TablePK = Pick<TableSchema, 'matchId' | 'round'>;
type TablePK = InferTablePrimaryKey<typeof table>;
// You can then use `TableSchema` as you would any other type.
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: TableSchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: { matchId: string, round: number }
const res = await table.insertOne(row);
With any of these strategies, you can use InferTableSchema
and InferTableReadSchema
to extract the exact read/write schemas.
For more information, see Collection and Table typing.
You can manually provide your own type for your tables by passing the type as a generic parameter to the createTable
method.
Optionally, you can provide your own type for the table’s primary key as a string literal union type of the primary key column names. For more information, see Get a table object.
This may be necessary if you modify the table’s default ser/des configuration.
The following example passes the manual types MySchema
and MyPK
to createTable
:
interface MySchema {
matchId: string,
round: number,
score: number,
winner: string,
when: DataAPITimestamp,
fighters: Set<UUID>,
mVector: DataAPIVector,
}
interface MyPK = Pick<MySchema, 'matchId' | 'round'>;
(async function bootstrap() {
const table = await db.createTable<MySchema, MyPK>('games', {
definition: {
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
}
});
// Use MySchema
as you would any other type
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: MySchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: { matchId: string, round: number }
const res = await table.insertOne(row);
})();
If you need to provide different schemas for reads and writes, see Collection and Table typing.
If you want to create a table without any typing, then you must pass SomeRow
as the single generic type parameter.
This types the table’s rows as Record<string, any>
, which is the most flexible but least type-safe option.
(async function bootstrap() {
const table = await db.createTable<SomeRow>('games', {
definition: {
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
}
});
// No typechecking anymore
await table.insertOne({ matchId: 'match01', round: 1, badfield: 'Shhh!' })
// res.insertedId :: SomeRow
const res = await table.insertOne(row);
})();
By default, the client creates the table in the database’s working keyspace.
To create a table in a specific keyspace, include keyspace
:
const table = await db.createTable<SomeRow>('games', {
definition: /* omitted for brevity \*/,
keyspace: 'KEYSPACE_NAME',
});
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The name of the table. |
|
|
The options for spawning the |
Options (CreateTableOptions<Schema>
):
Name | Type | Summary | ||
---|---|---|---|---|
|
|
A TypeScript object defining the table to create, including the following:
|
||
|
|
If If
|
||
|
|
The keyspace where you want to create the table.
If not specified, the working keyspace of the |
||
|
|
Optional parameter for tables that have a As an alternative to Astra DB KMS authentication, use Most embedding provider integrations accept a plain |
||
|
|
The configuration for logging events emitted by the |
||
|
|
The default timeout options for any operation performed on this |
||
|
|
Lower-level serialization/deserialization configuration for this table. For more information, see Custom Ser/Des. |
Returns:
Promise<Table<Schema, PKey>>
- A Promise
that resolves to the Table
instance representing the newly created table.
Example:
Full script
import { CreateTableDefinition, DataAPIClient, InferTableSchema, SomeRow, timestamp, uuid, vector } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax
const TableDefinition = <const>{ // <const> ensures the exact literal type of the object is used, not a widened type
columns: {
matchId: 'text', // Represented by a native JS string
round: 'tinyint', // All non-varint/decimal numbers are represented as JS numbers
mVector: { type: 'vector', dimension: 3 }, // Vectors are represented as DataAPIVectors by default to enable some optimizations
score: 'int',
when: 'timestamp', // Represented by DataAPITimestamps instead of Dates
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' }, // Sets/maps/lists are represented as native JS Sets/Maps/Arrays
}, // But the UUID is represented as a provided UUID class.
primaryKey: {
partitionBy: ['matchId'], // 'matchId' is the sole partition key
partitionSort: { round: 1 }, // 'round' is the sole clustering key
},
} satisfies CreateTableDefinition; // Ensures the table definition is valid
// Infer the TS-equivalent type from the table definition. Equivalent to:
//
// interface TableSchema {
// matchId: string, // Primary key components are not nullable
// round: number,
// score?: number | null, // Non-primary key columns are optional and can return as null
// winner?: string | null,
// when?: DataAPITimestamp | null,
// fighters?: Set<UUID>, // Maps, lists, and sets are optional to insert, but returns as empty instead of null
// mVector?: DataAPIVector | null, // Vectors can be null.
// }
//
// The preceding definition uses some custom types, like DataAPITimestamp, UUID, and DataAPIVector.
// If necessary, you can modify the ser/des logic to use different datatypes instead.
// However, you must provide your own types in that case.
// For more information, see the Typescript client usage documentation.
type TableSchema = InferTableSchema<typeof TableDefinition>;
(async function () {
// Create a table using the given TableSchema type or error if a 'games' table already exists
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Attempt to create the same table again.
// This errors because a table with the given name already exists,
// and it uses the default of 'ifNotExists: false'.
await db.createTable<TableSchema>('games', { definition: TableDefinition })
.catch((e => console.error(e.message)));
// Attempt to create the same table again.
// Because 'ifNotExists: true', the command does not throw an error
// if the working keyspace already has an table named 'games'.
await db.createTable<TableSchema>('games', { definition: TableDefinition, ifNotExists: true });
// Insert a single row
await table.insertOne({
matchId: 'match_0',
round: 1, // All non-varint/decimal numbers are represented as JS numbers
score: 18,
when: timestamp(), // Shorthand for new DataAPITimestamp(new Date())
winner: 'Victor',
fighters: new Set([ // Uses native Maps/Sets/Arrays for collections
uuid('a4e4e5b0-1f3b-4b4d-8e1b-4e6b3f1f3b4d'), // You can nest datatypes in collections
uuid(4), // Shorthand for UUID.v4()
]),
mVector: vector([0.2, -0.3, -0.5]), // Shorthand for new DataAPIVector([0.2, -0.3, -0.5])
});
// Use createTable to create an untyped reference to the table.
const untypedTable = await db.createTable<SomeRow>('games', { definition: TableDefinition, ifNotExists: true });
// Attempt to insert a row into the untyped table.
// This errors at runtime (not statically) because it's untyped.
await untypedTable.insertOne({ matchId: '32', round: 1, badfield: 3 })
.catch((e => console.error(e.message)));
// The following examples demonstrate various ways to get a reference to a table (a Table object)
// Create the table if it doesn't already exist, but don't retain the Table
object
await db.createTable('games', { definition: TableDefinition, ifNotExists: true });
// Create an untyped table object
const untypedTable = db.table('games');
// Flexible but not type-safe, errors at runtime
const inserted1 = await untypedTable.insertOne({ matchId: 'fight7' });
// Return type of inserted primary key not known either
console.log(inserted1.insertedId["I don't know who I am..."]);
// Return types of find operations, not type-safe
const found1 = await untypedTable.findOne({ matchId: 'fight7', round: 3 });
console.log(found1?.["I guess you could say that I'm having an IDentity crisis :)"]);
// Create a typed table object
const typedTable = db.table<TableSchema, TablePK>('games');
// @ts-expect-error
// Type-safe, errors when compiling
// You must ensure the types are correct
const inserted2 = await typedTable.insertOne({ matchId: 'fight7' });
// @ts-expect-error
// Type-safe, errors when compiling
console.log(inserted2.insertedId["uh oh I've been caught"]);
// Still type-safe
const found2 = await typedTable.findOne({ matchId: 'fight7', round: 3 })
console.log(found2?.winner);
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
// Create a table using the given TableSchema type or error if a 'games' table already exists
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Attempt to create the same table again.
// This errors because a table with the given name already exists,
// and it uses the default of 'ifNotExists: false'.
await db.createTable<TableSchema>('games', { definition: TableDefinition })
.catch((e => console.error(e.message)));
// Attempt to create the same table again.
// Because 'ifNotExists: true', the command does not throw an error
// if the working keyspace already has an table named 'games'.
await db.createTable<TableSchema>('games', { definition: TableDefinition, ifNotExists: true });
// Insert a single row
await table.insertOne({
matchId: 'match_0',
round: 1, // All non-varint/decimal numbers are represented as JS numbers
score: 18,
when: timestamp(), // Shorthand for new DataAPITimestamp(new Date())
winner: 'Victor',
fighters: new Set([ // Uses native Maps/Sets/Arrays for collections
uuid('a4e4e5b0-1f3b-4b4d-8e1b-4e6b3f1f3b4d'), // You can nest datatypes in collections
uuid(4), // Shorthand for UUID.v4()
]),
mVector: vector([0.2, -0.3, -0.5]), // Shorthand for new DataAPIVector([0.2, -0.3, -0.5])
});
// Use createTable to create an untyped reference to the table.
const untypedTable = await db.createTable<SomeRow>('games', { definition: TableDefinition, ifNotExists: true });
// Attempt to insert a row into the untyped table.
// This errors at runtime (not statically) because it's untyped.
await untypedTable.insertOne({ matchId: '32', round: 1, badfield: 3 })
.catch((e => console.error(e.message)));
For more information, see the Client reference.
Create a table in the database’s working keyspace by providing a TableDefinition
and specializations through options:
TableDefinition tableDefinition = new TableDefinition()
.addColumnText("match_id")
.addColumnInt("round")
.addColumnVector("m_vector",
new ColumnDefinitionVector().dimension(3).metric(COSINE))
.addColumn("score", ColumnTypes.INT)
.addColumn("when", ColumnTypes.TIMESTAMP)
.addColumn("winner", ColumnTypes.TEXT)
.addColumnSet("fighters", ColumnTypes.UUID)
.addPartitionBy("match_id")
.addPartitionSort(ascending("round"));
// Default Table Creation
Table<Row> tableGames = database
.createTable("games", tableDefinition);
You can use the following optional parameters to customize the createTable
operation:
-
Class<T>
(rowClass): Specify the type of the table’s row object. If not provided, the default isRow
. -
CreateTableOptions
: Granular control over thecreateTable
operation itself, such astimeouts
. -
TableOptions
: Options for the returnedTable<T>
object, such as specific timeouts for that object.
// Specify options at creation
CreateTableOptions createTableOptions = new CreateTableOptions()
.ifNotExists(true)
.embeddingAuthProvider(new EmbeddingAPIKeyHeaderProvider("api-key"))
.timeout(ofSeconds(5));
Table<Row> tableGames = database
.createTable("games", tableDefinition, createTableOptions);
// Change the Type of objects in use instead of default Row
Table<Game> tableGames = database
.createTable(
"games", // table name
tableDefinition, // table definition
Game.class, // bean for row
createTableOptions);
Additionally, instead of explicitly defining the TableDefinition
, you can use annotations to define the schema directly in your POJOs.
For example, given the following bean:
@EntityTable("game_ann1")
public class GameAnn1 {
@PartitionBy(0)
@Column(name ="match_id", type=TEXT )
private String matchId;
@PartitionSort(position = 0, order= SortOrder.ASCENDING)
@Column(name ="round", type=INT)
private Integer round;
@Column(name ="score", type=INT)
private Integer score;
@Column(name ="when", type=TIMESTAMP)
private Instant when;
@Column(name ="winner", type=TEXT)
private String winner;
@Column(name ="fighters", type=SET, valueType = UUID)
private Set<java.util.UUID> fighters;
@Column(name ="m_vector", type=VECTOR, dimension = 3, metric = SimilarityMetric.COSINE)
private DataAPIVector vector;
}
The following command creates a table with the name game_ann1
using the schema defined in the previously described GameAnn1
class:
Table<GameAnn1> tablGameAnn1 = database
.createTable(GameAnn1.class);
However, there are two ways to optimize the class:
-
If the column names in the POJO match the field names, then you can omit the property
name
in the@Column
annotation. -
If the column types in the POJO aren’t ambiguous, then you can omit the property
type
in the@Column
annotation.
The resulting simplified class is as follows:
@Data
@EntityTable("game_ann2")
public class Game {
private Integer score;
private Instant when;
private String winner;
private Set<UUID> fighters;
@PartitionBy(0)
@Column(name ="match_id")
private String matchId;
@PartitionSort(position = 0, order = SortOrder.ASCENDING)
private Integer round;
@Column(name ="m_vector", dimension = 3)
private DataAPIVector vector;
// getter, setters, constructor
}
Parameters:
Name | Type | Summary | ||
---|---|---|---|---|
|
|
The name of the table. |
||
|
A complete table definition for the table, including the column names, data types, other column settings, and the primary key. Some types require specific column definitions, particularly maps, lists, sets, and vector columns. For more information about all types, see Column data types. |
|||
|
|
An optional specification of the class of the table’s row object.
If not provided, the default is |
||
|
Options and additional parameters for the
|
Returns:
Table<T>
- A Table object that is typed as Table<Row>
by default.
To provide a more specific type hint, you must pass the rowClass
parameter matching the appropriate type hint for the variable used in the assignment.
For more information, see the following example.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.core.auth.EmbeddingAPIKeyHeaderProvider;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Game;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.definition.TableDefinition;
import com.datastax.astra.client.tables.TableOptions;
import com.datastax.astra.client.tables.definition.columns.ColumnDefinitionVector;
import com.datastax.astra.client.tables.definition.columns.ColumnTypes;
import com.datastax.astra.client.tables.commands.options.CreateTableOptions;
import com.datastax.astra.client.tables.definition.rows.Row;
import static com.datastax.astra.client.core.query.Sort.ascending;
import static com.datastax.astra.client.core.vector.SimilarityMetric.COSINE;
import static java.time.Duration.ofSeconds;
public class CreateTable {
public static void main(String[] args) {
// Database astraDb = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
// Definition of the table in fluent style
TableDefinition tableDefinition = new TableDefinition()
.addColumnText("match_id")
.addColumnInt("round")
.addColumnVector("m_vector",
new ColumnDefinitionVector().dimension(3).metric(COSINE))
.addColumn("score", ColumnTypes.INT)
.addColumn("when", ColumnTypes.TIMESTAMP)
.addColumn("winner", ColumnTypes.TEXT)
.addColumnSet("fighters", ColumnTypes.UUID)
.addPartitionBy("match_id")
.addPartitionSort(ascending("round"));
// Minimal creation
Table<Row> table1 =
db.createTable("games", tableDefinition);
// Minimal Creation with a Bean
Table<Game> table2 =
db.createTable("game2", tableDefinition, Game.class);
// One can add options to setup the creation with finer grained:
CreateTableOptions createTableOptions = new CreateTableOptions()
.keyspace("ks2")
.ifNotExists(true)
.embeddingAuthProvider(new EmbeddingAPIKeyHeaderProvider("api-key"))
.timeout(ofSeconds(5));
Table<Row> table3 =
db.createTable("game3", tableDefinition, createTableOptions);
}
}
To create a table, the JSON payload must include the table name, column definitions, and primary key definition.
The format of column definitions depends on the column’s data type.
For more information, see definition.columns
in this command’s Parameters table.
The primary key definition depends on the primary key type. The following examples demonstrate the JSON for the three primary key types. For more information, see Primary keys.
-
Single-column primary key
-
Composite primary key
-
Compound primary key
Create a table with a single-column primary key:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"createTable": {
"name": "TABLE_NAME",
"definition": {
"columns": {
"COLUMN_NAME": "DATA_TYPE",
"COLUMN_NAME": "DATA_TYPE"
},
"primaryKey": "COLUMN_NAME"
}
}
}' | jq
Create a table with a composite primary key:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"createTable": {
"name": "TABLE_NAME",
"definition": {
"columns": {
"COLUMN_NAME": {
"type": "DATA_TYPE"
},
"COLUMN_NAME": {
"type": "DATA_TYPE"
}
},
"primaryKey": {
"partitionBy": [
"COLUMN_NAME", "COLUMN_NAME"
]
}
}
}
}' | jq
Create a table with a compound primary key:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"createTable": {
"name": "TABLE_NAME",
"definition": {
"columns": {
"COLUMN_NAME": {
"type": "DATA_TYPE"
},
"COLUMN_NAME": {
"type": "DATA_TYPE"
}
},
"primaryKey": {
"partitionBy": [
"PARTITION_COLUMN_NAME"
]
"partitionSort": {
"SORT_COLUMN_NAME": -1
}
}
}
}
}' | jq
To store pre-generated vectors in a table, you must define a vector
column:
"columns": {
"COLUMN_NAME": "DATA_TYPE",
"COLUMN_NAME": "DATA_TYPE",
"VECTOR_COLUMN_NAME": {
"type": "vector",
"dimension": NUM_DIMENSIONS
}
}
To automatically generate embeddings with vectorize, define a vector
column with embedding provider service
options.
Astra DB stores the automatically-generated embeddings in this column.
"columns": {
"COLUMN_NAME": "DATA_TYPE",
"COLUMN_NAME": "DATA_TYPE",
"VECTOR_COLUMN_NAME": {
"type": "vector",
"dimension": NUM_DIMENSIONS,
"service": {
"provider": "EMBEDDINGS_PROVIDER_NAME",
"modelName": "MODEL_NAME",
"authentication": {
"providerKey": "ASTRA_KMS_API_KEY_NAME",
}
}
}
}
You can alter vector
columns at any time to change the vector configuration, including adding or removing a vectorize integration.
For more information about all aspects of vectors in tables, see Vector type.
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to create a table in a Serverless (Vector) database. It acts as a container for all the attributes and settings required to create the table. |
|
|
The name of the table. This must be unique within the database specified in the request URL. |
|
|
Contains the columns and primary key definition for the table. |
|
|
Defines the table’s columns as a series of key-value pairs where each key is a column name and each value is the column’s data type. Column names must be unique within a table. The Data API accepts column definitions in two formats:
Data types are enums of supported data types, such as For For the |
|
|
Defines the primary key for the table. For more information, see Primary keys. |
Returns:
A successful request returns 200 OK
.
Example response
{
"status": {
"ok": 1
}
}
Examples:
Create a table with a single-column primary key
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"createTable": {
"name": "students",
"definition": {
"columns": {
"name": "text",
"email": "text",
"graduated": "boolean",
"graduation_year": {
"type": "int"
},
"semester_gpas": {
"type": "list",
"valueType": "decimal"
},
"grades": {
"type": "map",
"keyType": "text",
"valueType": "int"
},
"extracurriculars": {
"type": "set",
"valueType": "text"
},
"vect_emb": {
"type": "vector",
"dimension": 1024
}
},
"primaryKey": "email"
}
}
}' | jq
Create a table with a composite primary key
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"createTable": {
"name": "students",
"definition": {
"columns": {
"name": "text",
"email": "text",
"graduated": "boolean",
"graduation_year": {
"type": "int"
},
"semester_gpas": {
"type": "list",
"valueType": "decimal"
},
"grades": {
"type": "map",
"keyType": "text",
"valueType": "int"
},
"extracurriculars": {
"type": "set",
"valueType": "text"
},
"vect_emb": {
"type": "vector",
"dimension": 1024
}
},
"primaryKey": {
"partitionBy": [
"name", "email"
]
}
}
}
}' | jq
Create a table with a compound primary key
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"createTable": {
"name": "students",
"definition": {
"columns": {
"name": "text",
"email": "text",
"graduated": "boolean",
"graduation_year": {
"type": "int"
},
"semester_gpas": {
"type": "list",
"valueType": "decimal"
},
"grades": {
"type": "map",
"keyType": "text",
"valueType": "int"
},
"extracurriculars": {
"type": "set",
"valueType": "text"
},
"vect_emb": {
"type": "vector",
"dimension": 1024
}
},
"primaryKey": {
"partitionBy": [
"graduation_year"
],
"partitionSort": {
"email": -1
}
}
}
}
}' | jq
Primary keys
The primary key is the unique identifier for rows in a table.
When you create a table, you define a primary key schema consisting of one or more columns. Column defined in the primary key are automatically indexed and available for querying. For more information about the role of indexes in tables, see Work with table indexes.
You cannot use Due to a known issue with filtering on |
There are three types of primary keys that you can define.
The type of key you use depends on your data model and the types of queries you plan to run.
The format of the primaryKey
in your table definition depends on the primary key type.
-
Single-column primary key
-
Composite primary key
-
Compound primary key
A single-column primary key is a primary key consisting of one column.
This option is best for use cases where you usually retrieve rows by a single value. For example, you could use this strategy for a small customer database where every customer is uniquely identified by their email address, and you always look up customers by their email address.
To define a single-column primary key, the primaryKey
is the column name as a string:
"primaryKey": "COLUMN_NAME"
For client-specific representations and more examples, see Create a table.
A composite primary key is a primary key consisting of multiple columns. The rows are uniquely identified by the combination of the values from each column.
This strategy can make queries more efficient by creating partitions (groups) of rows based on each primary key column.
For example, if your primary key includes country
and city
, the database has implicit groups of rows with the same country or city, making it more efficient to search for rows in a specific country or city.
This is a moderately complex strategy that allows for more nuanced queries and more complex unique identifiers. It can be useful if your rows are uniquely defined by values from multiple columns or your data falls into natural groupings, such as location or time. For example, you could use this strategy for scenarios such as the following:
-
A manufacturing database that uniquely identifies products by the production date, factory location, and SKU
-
A global customer database that groups customers by country or locality, in addition to an identifier, such as customer ID or email address
For composite primary keys, avoid columns with low cardinality (low diversity of values). For example, a customer database with an overabundance of customers from a single country might not benefit from partitioning by country. Instead, you could use locality identifiers, such as states or postal codes, to break large customer segments into smaller groups for more efficient queries.
To define a composite primary key, the primaryKey
is an object containing a partitionBy
array that contains the names of the columns to use for partitioning:
"primaryKey": {
"partitionBy": [
"COLUMN_NAME", "COLUMN_NAME"
]
}
For client-specific representations and more examples, see Create a table.
A compound primary key is a primary key consisting of partition (grouping) columns and clustering (sorting) columns. The rows are uniquely identified by the combination of the values from each column.
This is the most complex partitioning strategy, but it can provide the most flexibility and efficiency for querying data, if it is appropriate for your data model. This strategy can be useful for scenarios where you need to perform range queries or sort time-series data.
For example, assume you have a retail database where each row represents an order, and the orders are partitioned by customer ID and clustered by purchase date. In this case, the database implicitly groups each customer’s order together, and then sorts each customer’s orders by purchase date. This can make it more efficient to retrieve a customer’s most recent orders when they contact customer service or when they check the status of their orders in their account.
You can have multiple partition columns and multiple clustering columns. When clustering on multiple columns, the order you declare the columns matters. For example, if you cluster by date and name, the data is first sorted by the date, and then any rows with the same date are sorted by name.
In compound primary keys, avoid choosing clustering columns with high cardinality (high diversity of values), depending on your data model. For example, a purchase number column may not be ideal for clustering because it is unlikely to contain duplicates. Instead, choose clustering columns with moderate cardinality, such as purchase date, while avoiding columns with extremely low cardinality, such as booleans.
To define a compound primary key, the primaryKey
value is an object containing a partitionBy
array and a partitionSort
object:
-
partitionBy
is an array that contains the names of one or more columns to use for partitioning. -
partitionSort
is an object that contains key-value pairs defining clustering columns and the desired sort behavior.-1
indicates descending sorting and1
indicates ascending sorting.If
partitionSort
has multiple columns, sorting occurs in the order the columns are defined in thepartitionSort
object.
partitionBy
and partitionSort
must use different columns.
"primaryKey": {
"partitionBy": [
"PARTITION_COLUMN_NAME",
"PARTITION_COLUMN_NAME"
],
"partitionSort": {
"SORT_COLUMN_NAME": -1,
"SORT_COLUMN_NAME": 1
}
}
For client-specific representations and more examples, see Create a table.
Get a table object
Get a reference to an existing table for use with Data API clients.
This command returns a |
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Get a Table
object from a Database
using the working keyspace of the Database
:
my_table = database.get_table("games")
By default, get_table
uses the database’s working keyspace.
If necessary, you can specify a different keyspace, and you can pass other options for the resulting Table
object, such as an embedding_api_key
for header-based vectorize authentication:
my_table = database.get_table(
"games",
keyspace="the_other_keyspace",
embedding_api_key="secret-012abc...",
)
Get a typed Table
object by supplying a type (a subclass of TypedDict
) to its rows:
my_typed_table: Table[MyCustomDictType] = database.get_table(
"games",
row_type=MyCustomDictType,
)
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The name of the table. |
|
|
This parameter acts a formal specifier for the type checker.
If omitted, the resulting |
|
|
The keyspace containing the target table. If not specified, the general keyspace setting for the database is used. |
|
|
Optional parameter for tables that have a As an alternative to Astra DB KMS authentication, use Most embedding provider integrations accept a plain |
|
|
A complete or partial specification of the APIOptions to override the defaults inherited from the |
Returns:
Table
- A Table object that is typed as Table[dict]
by default.
To provide a more specific type hint, you must pass the row_type
parameter matching the appropriate type hint for the variable used in the assignment.
For more information, see the Example for this command.
Example response (reformatted for clarity)
Table(
name="COLLECTION_NAME",
keyspace="default_keyspace",
database.api_endpoint="ASTRA_DB_API_ENDPOINT",
api_options=FullAPIOptions(
token=StaticTokenProvider(APPLICATION_TOKEN),
...
),
...
)
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
from astrapy.constants import SortMode
from astrapy.info import (
CreateTableDefinition,
ColumnType,
)
database.create_table(
"games",
definition=(
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.TINYINT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
),
)
# Get a Table object (and read a property of it as an example):
my_table = database.get_table("games")
my_table.full_name
# 'default_keyspace.games'
# Get a Table object in a specific keyspace,
# and set an embedding API key to it:
my_other_table = database.get_table(
"tournaments",
keyspace="the_other_keyspace",
embedding_api_key="secret-012abc...",
)
from astrapy import Table
MyCustomDictType = dict[str, int]
# Get a Table object typed with a specific type for its rows:
my_typed_table: Table[MyCustomDictType] = database.get_table(
"games",
row_type=MyCustomDictType,
)
For more information, see the Client reference.
To spawn a Table
instance, you must pass a type schema.
The TypeScript client offers several ways to type tables, depending on your typing preferences and needs.
-
Schema
-
Schema and primary key
-
Untyped
-
Full generic type signature
The most straightforward way to type a table is to provide a schema object that represents the table’s structure. However, this strategy doesn’t provide any type information about the table’s primary key.
import { DataAPIClient, DataAPITimestamp, DataAPIVector, UUID } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Define table's type manually
interface TableSchema {
matchId: string,
round: number,
score: number,
winner: string,
when: DataAPITimestamp,
fighters: Set<UUID>,
mVector: DataAPIVector,
}
// Pass it to db.table to type it as such.
// You must ensure the schema matches the table's actual schema.
const table = db.table<TableSchema>('games');
// You can then use TableSchema as you would any other type.
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: TableSchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: Partial<TableSchema>
const res = await table.insertOne(row);
The primary key type is used in the return types of insertOne
and insertMany
operations only.
However, you don’t need to specify the primary key type if you use the default Partial<Schema>
as the primary key type or you don’t need to use the returned values from insertOne
and insertMany
operations.
Partial<Schema>
keeps the return type type-safe when the primary key fields are not known.
For example, given the following schema:
interface SchemaWithNoPK {
ptKey: string, // We know this is part of the primary key; TypeScript doesn't
clKey: string,
val1?: string | null,
val2?: number | null,
}
const table = db.table<SchemaWithNoPK>('my_table');
If there is no primary key information provided, then insertOne
returns an insertedId
like the following:
// `insertedId` is inferred to be `Partial<SchemaWithNoPK>` by default
const inserted = await table.insertOne({ ptKey: 'abc', clKey: 'def', val1: 'val' });
const insertedId = inserted.insertedId;
While not perfect, this option remains relatively type-safe without necessitating that you embed your primary key’s type in the table’s schema’s type itself.
If the primary key type is unspecified, the actual default is Partial<RSchema>
, but the difference between Partial<RSchema>
and Partial<Schema>
is negligible for most use cases.
For more information about read and write schemas, see Full generic type signature.
For more precise typing, you can include the primary key information in the table’s type along with the schema.
This strategy requires the TS-native Pick
utility type to define the primary key type.
import { DataAPIClient, DataAPITimestamp, DataAPIVector, UUID } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Define table's type manually
interface TableSchema {
matchId: string,
round: number,
score: number,
winner: string,
when: DataAPITimestamp,
fighters: Set<UUID>,
mVector: DataAPIVector,
}
// Define table's primary key type
type TablePK = Pick<TableSchema, 'matchId' | 'round'>;
// Pass it to db.table to type it as such.
// You must ensure the schema matches the table's actual schema.
const table = db.table<TableSchema, TablePK>('games');
// You can then use TableSchema as you would any other type.
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: TableSchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: { matchId: string, round: number }
const res = await table.insertOne(row);
If you want to use a table without any typing, you can pass SomeRow
as the single generic type parameter.
This types the table’s rows as Record<string, any>
, which is the most flexible but least type-safe option.
import { DataAPIClient } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Pass it to db.table to type it as such.
// You must ensure the schema matches the table's actual schema.
const table = db.table<TableSchema, TablePK>('games');
// You can then use TableSchema as you would any other type.
// @ts-expect-error - 'badfield' is not a valid column as per the table's type
const row: TableSchema = { matchId: 'match01', round: 1, badfield: 'Shhh!' }
// res.insertedId :: { matchId: string, round: number }
const res = await table.insertOne(row);
For the most complex use cases, especially when using custom ser/des logic, consider using the Table
full generic type signature:
class Table<
WSchema extends SomeRow,
PKey extends SomeRow = Partial<FoundRow<WSchema>>,
RSchema extends SomeRow = FoundRow<WSchema>,
> {}
For more information, see Collection and Table typing.
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The name of the table. |
|
|
The options for spawning the |
Options (TableOptions<Schema>
):
Name | Type | Summary |
---|---|---|
|
|
The keyspace where the target table exists.
If not specified, the working keyspace of the
|
|
|
Optional parameter for tables that have a As an alternative to Astra DB KMS authentication, use Most embedding provider integrations accept a plain |
|
|
The configuration for logging events emitted by the |
|
|
The default timeout options for any operation performed on this |
|
|
Lower-level serialization/deserialization configuration for this table. For more information, see Custom Ser/Des. |
Returns:
Table<Schema>
- An unvalidated reference to the table.
The type parameter Schema
is used for type inference in the client library.
You must ensure that the schema matches the actual table schema.
Example:
Full script
import { CreateTableDefinition, DataAPIClient, InferTableSchema, SomeRow, timestamp, uuid, vector } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax
const TableDefinition = <const>{ // <const> ensures the exact literal type of the object is used, not a widened type
columns: {
matchId: 'text', // Represented by a native JS string
round: 'tinyint', // All non-varint/decimal numbers are represented as JS numbers
mVector: { type: 'vector', dimension: 3 }, // Vectors are represented as DataAPIVectors by default to enable some optimizations
score: 'int',
when: 'timestamp', // Represented by DataAPITimestamps instead of Dates
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' }, // Sets/maps/lists are represented as native JS Sets/Maps/Arrays
}, // But the UUID is represented as a provided UUID class.
primaryKey: {
partitionBy: ['matchId'], // 'matchId' is the sole partition key
partitionSort: { round: 1 }, // 'round' is the sole clustering key
},
} satisfies CreateTableDefinition; // Ensures the table definition is valid
// Infer the TS-equivalent type from the table definition. Equivalent to:
//
// interface TableSchema {
// matchId: string, // Primary key components are not nullable
// round: number,
// score?: number | null, // Non-primary key columns are optional and can return as null
// winner?: string | null,
// when?: DataAPITimestamp | null,
// fighters?: Set<UUID>, // Maps, lists, and sets are optional to insert, but returns as empty instead of null
// mVector?: DataAPIVector | null, // Vectors can be null.
// }
//
// The preceding definition uses some custom types, like DataAPITimestamp, UUID, and DataAPIVector.
// If necessary, you can modify the ser/des logic to use different datatypes instead.
// However, you must provide your own types in that case.
// For more information, see the Typescript client usage documentation.
type TableSchema = InferTableSchema<typeof TableDefinition>;
(async function () {
// Create a table using the given TableSchema type or error if a 'games' table already exists
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Attempt to create the same table again.
// This errors because a table with the given name already exists,
// and it uses the default of 'ifNotExists: false'.
await db.createTable<TableSchema>('games', { definition: TableDefinition })
.catch((e => console.error(e.message)));
// Attempt to create the same table again.
// Because 'ifNotExists: true', the command does not throw an error
// if the working keyspace already has an table named 'games'.
await db.createTable<TableSchema>('games', { definition: TableDefinition, ifNotExists: true });
// Insert a single row
await table.insertOne({
matchId: 'match_0',
round: 1, // All non-varint/decimal numbers are represented as JS numbers
score: 18,
when: timestamp(), // Shorthand for new DataAPITimestamp(new Date())
winner: 'Victor',
fighters: new Set([ // Uses native Maps/Sets/Arrays for collections
uuid('a4e4e5b0-1f3b-4b4d-8e1b-4e6b3f1f3b4d'), // You can nest datatypes in collections
uuid(4), // Shorthand for UUID.v4()
]),
mVector: vector([0.2, -0.3, -0.5]), // Shorthand for new DataAPIVector([0.2, -0.3, -0.5])
});
// Use createTable to create an untyped reference to the table.
const untypedTable = await db.createTable<SomeRow>('games', { definition: TableDefinition, ifNotExists: true });
// Attempt to insert a row into the untyped table.
// This errors at runtime (not statically) because it's untyped.
await untypedTable.insertOne({ matchId: '32', round: 1, badfield: 3 })
.catch((e => console.error(e.message)));
// The following examples demonstrate various ways to get a reference to a table (a Table object)
// Create the table if it doesn't already exist, but don't retain the Table
object
await db.createTable('games', { definition: TableDefinition, ifNotExists: true });
// Create an untyped table object
const untypedTable = db.table('games');
// Flexible but not type-safe, errors at runtime
const inserted1 = await untypedTable.insertOne({ matchId: 'fight7' });
// Return type of inserted primary key not known either
console.log(inserted1.insertedId["I don't know who I am..."]);
// Return types of find operations, not type-safe
const found1 = await untypedTable.findOne({ matchId: 'fight7', round: 3 });
console.log(found1?.["I guess you could say that I'm having an IDentity crisis :)"]);
// Create a typed table object
const typedTable = db.table<TableSchema, TablePK>('games');
// @ts-expect-error
// Type-safe, errors when compiling
// You must ensure the types are correct
const inserted2 = await typedTable.insertOne({ matchId: 'fight7' });
// @ts-expect-error
// Type-safe, errors when compiling
console.log(inserted2.insertedId["uh oh I've been caught"]);
// Still type-safe
const found2 = await typedTable.findOne({ matchId: 'fight7', round: 3 })
console.log(found2?.winner);
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
Expand the preceding Full script example for the definition of TypeSchema
that is used in the following truncated example:
// Create the table if it doesn't already exist, but don't retain the Table
object
await db.createTable('games', { definition: TableDefinition, ifNotExists: true });
// Create an untyped table object
const untypedTable = db.table('games');
// Flexible but not type-safe, errors at runtime
const inserted1 = await untypedTable.insertOne({ matchId: 'fight7' });
// Return type of inserted primary key not known either
console.log(inserted1.insertedId["I don't know who I am..."]);
// Return types of find operations, not type-safe
const found1 = await untypedTable.findOne({ matchId: 'fight7', round: 3 });
console.log(found1?.["I guess you could say that I'm having an IDentity crisis :)"]);
// Create a typed table object
const typedTable = db.table<TableSchema, TablePK>('games');
// @ts-expect-error
// Type-safe, errors when compiling
// You must ensure the types are correct
const inserted2 = await typedTable.insertOne({ matchId: 'fight7' });
// @ts-expect-error
// Type-safe, errors when compiling
console.log(inserted2.insertedId["uh oh I've been caught"]);
// Still type-safe
const found2 = await typedTable.findOne({ matchId: 'fight7', round: 3 })
console.log(found2?.winner);
For more information, see the Client reference.
Get a Table
object from a Database
using the working keyspace of the Database
:
Table<Row> myTable = database.getTable("games");
By default, getTable
uses the database’s working keyspace.
If necessary, you can specify a different keyspace, and you can pass other options for the resulting Table
object, such as an embeddingApiKey
for header-based vectorize authentication:
TableOptions options = new TableOptions()
.keyspace("the_other_keyspace")
.embeddingApiKey("secret-012abc...");
Table<Row> myTable = db.getTable("games", options);
Get a typed Table
object by supplying a type to its rows:
TableOptions options = new TableOptions();
Table<Game> myTable = database
.getTable("games", Game.class, options);
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The name of the table. |
|
|
An optional specification of the class of the table’s row object.
If not provided, the default is |
|
Specialization of the |
Options:
Name | Type | Summary |
---|---|---|
|
|
The keyspace containing the target table.
If not specified, the working keyspace of the |
|
|
Optional configuration for default timeouts for table operations using this |
|
|
Optional specialized headers for this table, if needed, that are added to the database headers. |
|
|
Optional parameter for tables that have a As an alternative to Astra DB KMS authentication, use Most embedding provider integrations accept a plain |
|
An optional specialization associated with |
|
|
Optional HTTP configuration overrides for this |
|
|
Optional specialized serializer for this |
Returns:
Table<T>
- A Table object that is typed as Table<Row>
by default.
To provide a more specific type hint, you must pass the rowClass
parameter matching the appropriate type hint for the variable used in the assignment.
For more information, see the following example.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.core.auth.EmbeddingAPIKeyHeaderProvider;
import com.datastax.astra.client.core.options.DataAPIClientOptions;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Game;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.TableOptions;
import com.datastax.astra.client.tables.definition.rows.Row;
import java.util.Map;
public class GetTable {
public static void main(String[] args) {
// Database astraDb = new DataAPIClient(token).getDatabase(endpoint);
Database db =
DataAPIClients.localDbWithDefaultKeyspace();
// Default
Table<Row> myTable1 =
db.getTable("games");
// Options
TableOptions options = new TableOptions()
.keyspace("the_other_keyspace")
.embeddingApiKey("secret-012abc...")
.databaseAdditionalHeaders(Map.of("Feature-Flag-tables", "true"));
Table<Row> myTable3 = db.getTable("games", options);
// Typing
Table<Game> myTable2 =
db.getTable("games", Game.class);
// Typing + Options
Table<Game> myTable4 =
db.getTable("games", Game.class, new TableOptions());
}
}
This operation is not required with HTTP because you specify the target table in the path or body of the request, if required.
To get information about tables in a database, see List table metadata.
Alter a table
Modify the configuration of a previously-created table:
The Data API does not support operations that alter a column’s type or rename a table. To achieve either of these goals, you must drop and recreate the column or table. |
Add columns
Add one or more columns to an existing table. Columns are defined in the same way as they are when you create a table.
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Add a column to a table:
my_table.alter(
AlterTableAddColumns(
columns={
"tie_break": TableScalarColumnTypeDescriptor(
column_type=ColumnType.BOOLEAN,
),
},
),
)
Add columns to a table, and use the return value for strict control over types:
new_table: Table[MyCustomDictType] = my_table.alter(
AlterTableAddColumns(
columns={
"tie_break": TableScalarColumnTypeDescriptor(
column_type=ColumnType.BOOLEAN,
),
"venue": TableScalarColumnTypeDescriptor(
column_type=ColumnType.TEXT,
),
},
),
row_type=MyCustomDictType,
)
Parameters:
Name | Type | Summary |
---|---|---|
|
|
An instance of |
|
|
This parameter acts a formal specifier for the type checker.
If omitted, the resulting |
|
|
A timeout, in milliseconds, to impose on the underlying API request.
If not provided, the |
Returns:
Table
- A new Table
instance formally representing the table after the schema change.
While you can continue working with the original class instance, stricter typing is achieved by providing a type hint to the new shape of the rows in the table, with a proper subclass of TypedDict
, and using the return value of this method immediately.
Example response (reformatted for clarity)
Table(
name="COLLECTION_NAME",
keyspace="default_keyspace",
database.api_endpoint="ASTRA_DB_API_ENDPOINT",
api_options=FullAPIOptions(
token=StaticTokenProvider(APPLICATION_TOKEN),
...
),
...
)
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
from astrapy.constants import SortMode
from astrapy.info import (
CreateTableDefinition,
ColumnType,
)
my_table = database.create_table(
"games",
definition=(
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.TINYINT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
),
)
from astrapy.info import (
AlterTableAddColumns,
ColumnType,
TableScalarColumnTypeDescriptor,
)
# Add a column
new_table = my_table.alter(
AlterTableAddColumns(
columns={
"tie_break": TableScalarColumnTypeDescriptor(
column_type=ColumnType.BOOLEAN,
),
},
),
)
For more information, see the Client reference.
Add columns to the table, and update the Table
type:
const newTable = await table.alter<NewSchema>({
operation: {
add: {
columns: {
tieBreak: 'boolean',
venue: 'text',
},
},
},
});
Parameters:
Name | Type | Summary |
---|---|---|
|
|
Defines an operation to alter a table by adding one or more columns. |
|
|
The client-side timeout for this operation. |
Options (AddColumnOperation
):
Name | Type | Summary |
---|---|---|
|
|
The column names, data types, and other settings (if required) for the new columns. Column are defined in the same way as they are in |
Returns:
Promise<Table<NewSchema>>
- A promise which resolves to the table object recast as its new type after the alter operation.
Don’t use the original table type. Continuing to use the original table’s type causes the type of the table to desync from the table’s actual schema.
Example:
Full script
import { CreateTableDefinition, DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
// Infer the table type from the table definition.
// For information about table typing, see the documentation for create table.
type TableSchema = InferTableSchema<typeof TableDefinition>;
// The following script demonstrates all alter operations: add, drop, addVectorize, dropVectorize.
// This example also inserts rows to demonstrate the goal and outcome of each alter operation.
// You can only run one alter operation at a time, but you can have multiple operations in the same script.
(async function () {
// Create a table or error if a 'games' table already exists.
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Represents the new schema of the table after the alter to add columns
type NewSchema = TableSchema & {
tieBreak: boolean;
venue: string;
}
// @ts-expect-error
// Try to insert data into nonexistent columns.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
// Columns are defined in the same way that you define them in createTable, including name, type, and other properties.
const altered = await table.alter<NewSchema>({
operation: {
add: {
columns: {
tieBreak: 'boolean',
venue: 'text',
},
},
},
});
// Attempt to insert the rows again.
// This should succeed now that all columns exist in the table.
const inserted = await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' });
console.log('inserted', inserted.insertedId);
// Represents the new schema of the table after the alter to drop columns
type NewSchema = Omit<TableSchema, 'tieBreak' | 'venue'>
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
const altered = await table.alter<NewSchema>({
operation: {
drop: {
columns: ['tieBreak', 'venue'],
},
},
});
// @ts-expect-error
// Try to insert data into the removed columns.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// @ts-expect-error
// Try to use vectorize on a vector column that doesn't have a vectorize integration.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Add the OpenAI embedding provider integration to the vector column.
const altered = await table.alter({
operation: {
addVectorize: {
columns: {
mVector: {
provider: 'openai',
modelName: 'text-embedding-3-small',
authentication: {
providerKey: 'ASTRA_KMS_API_KEY_NAME',
},
},
},
},
},
});
// Attempt to insert the row again.
// This should succeed now that the vector column has a vectorize integration.
const inserted = await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' });
console.log('inserted', inserted.insertedId);
// Remove vectorize from the specified vector column
const altered = await table.alter({
operation: {
dropVectorize: {
columns: ['mVector'],
},
},
});
// @ts-expect-error
// Try to use vectorize on the vector column that no longer has a vectorize integration.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
Expand the preceding Full script example for the definition of NewSchema
that is used in the following truncated example:
// @ts-expect-error
// Try to insert data into nonexistent columns.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
// Columns are defined in the same way that you define them in createTable, including name, type, and other properties.
const altered = await table.alter<NewSchema>({
operation: {
add: {
columns: {
tieBreak: 'boolean',
venue: 'text',
},
},
},
});
// Attempt to insert the rows again.
// This should succeed now that all columns exist in the table.
const inserted = await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' });
console.log('inserted', inserted.insertedId);
For more information, see the Client reference.
Add a column to a table:
AlterTableAddColumns alterOperation = new AlterTableAddColumns()
.addColumnBoolean("tie_break");
Table<Game> tableRow = myTable.alter(alterOperation);
Add columns to a table, providing a new row type, and specialize some options:
AlterTableAddColumns alterOperation = new AlterTableAddColumns()
.addColumnBoolean("tie_break")
.addColumnText("venue");
AlterTableOptions alterOptions = new AlterTableOptions()
.timeout(10000L);
// Notice the type hint for the new table
Table<EnhanceGame> myUpdatedTable = myTable
.alter(alterOperation, alterOptions, EnhanceGame.class);
Parameters:
Name | Type | Summary |
---|---|---|
|
Defines an operation to alter a table by adding one or more columns. |
|
|
Specialization of the operation, including |
|
|
|
An optional new type for the row object.
If not provided, the default is |
Returns:
Table<NewBean>
- The table object recast as its new type after the alter operation is complete.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.commands.AlterTableAddColumns;
import com.datastax.astra.client.tables.definition.rows.Row;
public class AlterTableAddColumn {
public static void main(String[] args) {
// Database db = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
Table<Row> myTable1 = db.getTable("games");
// Add A Columns
AlterTableAddColumns add = new AlterTableAddColumns()
.addColumnBoolean("tie_break")
.addColumnText("venue");
myTable1.alter(add);
}
}
Add a new column:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE/ASTRA_DB_TABLE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"add": {
"columns": {
"NEW_COLUMN_NAME": "DATA_TYPE"
}
}
}
}
}' | jq
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to modify the configuration of a table in a Serverless (Vector) database. It acts as a container for all the attributes and settings required to modify the table. |
|
|
Specifies that you want to add a column to the table. |
|
|
Define columns to add to the table. The format is the same as when you define |
Returns:
Table<NewBean>
- The table object re-casted as its new type once the alter operation is complete.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.commands.AlterTableAddColumns;
import com.datastax.astra.client.tables.commands.AlterTableDropColumns;
import com.datastax.astra.client.tables.definition.rows.Row;
public class AlterTableDropColumn {
public static void main(String[] args) {
// Database db = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
Table<Row> myTable1 = db.getTable("games");
// Add A Columns
AlterTableDropColumns dropColumn = new AlterTableDropColumns("tie_break");
myTable1.alter(dropColumn);
}
}
Example:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace/students" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"add": {
"columns": {
"deans_list": "boolean"
}
}
}
}
}' | jq
Drop columns
Remove one or more columns from an existing table.
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Drop a column from a table:
new_table = my_table.alter(AlterTableDropColumns(
columns=["tie_break"],
))
Drop columns from a table and use the return value for strict control over types:
new_table: Table[MyCustomNarrowDictType] = my_table.alter(
AlterTableDropColumns(
columns=["tie_break", "venue"],
),
row_type=MyCustomNarrowDictType,
)
Parameters:
Name | Type | Summary |
---|---|---|
|
|
An instance of |
|
|
This parameter acts a formal specifier for the type checker.
If omitted, the resulting |
|
|
A timeout, in milliseconds, to impose on the underlying API request.
If not provided, the |
Returns:
Table
- A new Table
instance formally representing the table after the schema change.
While you can continue working with the original class instance, stricter typing is achieved by providing a type hint to the new shape of the rows in the table, with a proper subclass of TypedDict
, and using the return value of this method immediately.
Example response
The following example repsonse is reformatted for clarity:
Table(
name="COLLECTION_NAME",
keyspace="default_keyspace",
database.api_endpoint="ASTRA_DB_API_ENDPOINT",
api_options=FullAPIOptions(
token=StaticTokenProvider(APPLICATION_TOKEN),
...
),
...
)
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
from astrapy.constants import SortMode
from astrapy.info import (
CreateTableDefinition,
ColumnType,
)
my_table = database.create_table(
"games",
definition=(
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.TINYINT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
),
)
from astrapy.info import (
AlterTableAddColumns,
ColumnType,
TableScalarColumnTypeDescriptor,
)
# Add a column
new_table = my_table.alter(
AlterTableAddColumns(
columns={
"tie_break": TableScalarColumnTypeDescriptor(
column_type=ColumnType.BOOLEAN,
),
},
),
)
# Drop a column
from astrapy.info import AlterTableDropColumns
new_table = my_table.alter(AlterTableDropColumns(
columns=["tie_break"],
))
For more information, see the Client reference.
Drop columns from the table and update the Table
type:
const newTable = await table.alter<NewSchema>({
operation: {
drop: {
columns: ['tieBreak', 'venue'],
},
},
});
Parameters:
Name | Type | Summary |
---|---|---|
|
|
Defines an operation to alter a table by dropping one or more columns. |
|
|
The client-side timeout for this operation. |
Options (DropColumnOperation
):
Name | Type | Summary |
---|---|---|
|
|
The names of the columns to drop from the table. |
Returns:
Promise<Table<NewSchema>> - A promise which resolves to the table object recast as its new type after the alter operation is complete.
Don’t use the orginal table’s type. Continuing to use the original table’s type causes the type of the table to desync from the table’s actual schema.
Example:
Full script
import { CreateTableDefinition, DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
// Infer the table type from the table definition.
// For information about table typing, see the documentation for create table.
type TableSchema = InferTableSchema<typeof TableDefinition>;
// The following script demonstrates all alter operations: add, drop, addVectorize, dropVectorize.
// This example also inserts rows to demonstrate the goal and outcome of each alter operation.
// You can only run one alter operation at a time, but you can have multiple operations in the same script.
(async function () {
// Create a table or error if a 'games' table already exists.
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Represents the new schema of the table after the alter to add columns
type NewSchema = TableSchema & {
tieBreak: boolean;
venue: string;
}
// @ts-expect-error
// Try to insert data into nonexistent columns.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
// Columns are defined in the same way that you define them in createTable, including name, type, and other properties.
const altered = await table.alter<NewSchema>({
operation: {
add: {
columns: {
tieBreak: 'boolean',
venue: 'text',
},
},
},
});
// Attempt to insert the rows again.
// This should succeed now that all columns exist in the table.
const inserted = await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' });
console.log('inserted', inserted.insertedId);
// Represents the new schema of the table after the alter to drop columns
type NewSchema = Omit<TableSchema, 'tieBreak' | 'venue'>
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
const altered = await table.alter<NewSchema>({
operation: {
drop: {
columns: ['tieBreak', 'venue'],
},
},
});
// @ts-expect-error
// Try to insert data into the removed columns.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// @ts-expect-error
// Try to use vectorize on a vector column that doesn't have a vectorize integration.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Add the OpenAI embedding provider integration to the vector column.
const altered = await table.alter({
operation: {
addVectorize: {
columns: {
mVector: {
provider: 'openai',
modelName: 'text-embedding-3-small',
authentication: {
providerKey: 'ASTRA_KMS_API_KEY_NAME',
},
},
},
},
},
});
// Attempt to insert the row again.
// This should succeed now that the vector column has a vectorize integration.
const inserted = await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' });
console.log('inserted', inserted.insertedId);
// Remove vectorize from the specified vector column
const altered = await table.alter({
operation: {
dropVectorize: {
columns: ['mVector'],
},
},
});
// @ts-expect-error
// Try to use vectorize on the vector column that no longer has a vectorize integration.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
Expand the preceding Full script example for the definition of NewSchema
that is used in the following truncated example:
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
const altered = await table.alter<NewSchema>({
operation: {
drop: {
columns: ['tieBreak', 'venue'],
},
},
});
// @ts-expect-error
// Try to insert data into the removed columns.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
For more information, see the Client reference.
Drop a column from a table:
myTable.alter(new AlterTableDropColumns("tie_break"));
Drop columns from a table, use the return value for strict control over types, and specialize with options:
AlterTableDropColumns alterOperation = new AlterTableDropColumns()
.columns("tie_break", "venue");
AlterTableOptions alterOptions = new AlterTableOptions()
.timeout(10000L);
Table<Game> myUpdatedTable = myTable
.alter(alterOperation, alterOptions, Game.class);
Parameters:
Name | Type | Summary |
---|---|---|
|
Defines an operation to alter a table by dropping one or more columns. |
|
|
Specialization of the operation, such as |
|
|
|
Optional new type for the row object.
If not provided, the default is |
Returns:
Table<NewBean>
- The table object recast as its new type after the alter operation is complete.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.commands.AlterTableAddColumns;
import com.datastax.astra.client.tables.commands.AlterTableDropColumns;
import com.datastax.astra.client.tables.definition.rows.Row;
public class AlterTableDropColumn {
public static void main(String[] args) {
// Database db = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
Table<Row> myTable1 = db.getTable("games");
// Add A Columns
AlterTableDropColumns dropColumn = new AlterTableDropColumns("tie_break");
myTable1.alter(dropColumn);
}
}
Drop a column:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE/ASTRA_DB_TABLE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"drop": {
"columns": [ "COLUMN_NAME", "COLUMN_NAME" ]
}
}
}
}' | jq
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to modify the configuration of a table in a Serverless (Vector) database. It acts as a container for all the attributes and settings required to modify the table. |
|
|
Specifies that you want to remove a column from the table. |
|
|
The names of the columns to remove from the table. |
Returns:
A successful request returns 200 OK
.
Example response
{
"status": {
"ok": 1
}
}
Example:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace/students" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"drop": {
"columns": [ "deans_list" ]
}
}
}
}' | jq
Add vectorize to columns
To automatically generate embeddings with vectorize, you configure an embedding provider integration on a vector
column.
Astra DB stores the automatically-generated embeddings in this column.
This operation adds an embedding provider integration to an existing vector
column.
You can modify multiple vector
columns in a single request.
For information about inserting vector data and automatically generating embeddings in tables, see Vector type and Insert rows reference.
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Add vectorize to a column:
my_table.alter(
AlterTableAddVectorize(
columns={
"m_vector": VectorServiceOptions(
provider="openai",
model_name="text-embedding-3-small",
authentication={
"providerKey": "ASTRA_KMS_API_KEY_NAME",
},
),
},
),
)
Parameters:
Name | Type | Summary |
---|---|---|
|
|
An instance of |
|
|
DataStax does not recommend using |
|
|
A timeout, in milliseconds, to impose on the underlying API request.
If not provided, the |
Returns:
Table
- A new table object that is only useful for type-hints purposes.
Do not use the new Table
instance.
Instead, continue to use the original Table
instance for this table.
Example response
The following example response is reformatted for clarity:
Table(
name="COLLECTION_NAME",
keyspace="default_keyspace",
database.api_endpoint="ASTRA_DB_API_ENDPOINT",
api_options=FullAPIOptions(
token=StaticTokenProvider(APPLICATION_TOKEN),
...
),
...
)
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
from astrapy.constants import SortMode
from astrapy.info import (
CreateTableDefinition,
ColumnType,
)
my_table = database.create_table(
"games",
definition=(
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.TINYINT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
),
)
from astrapy.info import AlterTableAddVectorize, VectorServiceOptions
new_table = my_table.alter(
AlterTableAddVectorize(
columns={
"m_vector": VectorServiceOptions(
provider="openai",
model_name="text-embedding-3-small",
authentication={
"providerKey": "ASTRA_KMS_API_KEY_NAME",
},
),
},
),
)
For more information, see the Client reference.
Add vectorize to a column:
const newTable = await table.alter({
operation: {
addVectorize: {
columns: {
mVector: {
provider: 'openai',
modelName: 'text-embedding-3-small',
authentication: {
providerKey: 'ASTRA_KMS_API_KEY_NAME',
},
},
},
},
},
});
Parameters:
Name | Type | Summary |
---|---|---|
|
|
Defines an operation to alter a table by adding a vectorize integration to one or more |
|
|
The client-side timeout for this operation. |
Options (AddVectorizeOperation
):
Name | Type | Summary |
---|---|---|
|
|
Specify the names of the |
Returns:
Promise<Table<Schema>>
- A promise which resolves to the Table
object once the alter operation is complete.
Example:
Full script
import { CreateTableDefinition, DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
// Infer the table type from the table definition.
// For information about table typing, see the documentation for create table.
type TableSchema = InferTableSchema<typeof TableDefinition>;
// The following script demonstrates all alter operations: add, drop, addVectorize, dropVectorize.
// This example also inserts rows to demonstrate the goal and outcome of each alter operation.
// You can only run one alter operation at a time, but you can have multiple operations in the same script.
(async function () {
// Create a table or error if a 'games' table already exists.
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Represents the new schema of the table after the alter to add columns
type NewSchema = TableSchema & {
tieBreak: boolean;
venue: string;
}
// @ts-expect-error
// Try to insert data into nonexistent columns.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
// Columns are defined in the same way that you define them in createTable, including name, type, and other properties.
const altered = await table.alter<NewSchema>({
operation: {
add: {
columns: {
tieBreak: 'boolean',
venue: 'text',
},
},
},
});
// Attempt to insert the rows again.
// This should succeed now that all columns exist in the table.
const inserted = await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' });
console.log('inserted', inserted.insertedId);
// Represents the new schema of the table after the alter to drop columns
type NewSchema = Omit<TableSchema, 'tieBreak' | 'venue'>
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
const altered = await table.alter<NewSchema>({
operation: {
drop: {
columns: ['tieBreak', 'venue'],
},
},
});
// @ts-expect-error
// Try to insert data into the removed columns.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// @ts-expect-error
// Try to use vectorize on a vector column that doesn't have a vectorize integration.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Add the OpenAI embedding provider integration to the vector column.
const altered = await table.alter({
operation: {
addVectorize: {
columns: {
mVector: {
provider: 'openai',
modelName: 'text-embedding-3-small',
authentication: {
providerKey: 'ASTRA_KMS_API_KEY_NAME',
},
},
},
},
},
});
// Attempt to insert the row again.
// This should succeed now that the vector column has a vectorize integration.
const inserted = await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' });
console.log('inserted', inserted.insertedId);
// Remove vectorize from the specified vector column
const altered = await table.alter({
operation: {
dropVectorize: {
columns: ['mVector'],
},
},
});
// @ts-expect-error
// Try to use vectorize on the vector column that no longer has a vectorize integration.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
// @ts-expect-error
// Try to use vectorize on a vector column that doesn't have a vectorize integration.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Add the OpenAI embedding provider integration to the vector column.
const altered = await table.alter({
operation: {
addVectorize: {
columns: {
mVector: {
provider: 'openai',
modelName: 'text-embedding-3-small',
authentication: {
providerKey: 'ASTRA_KMS_API_KEY_NAME',
},
},
},
},
},
});
// Attempt to insert the row again.
// This should succeed now that the vector column has a vectorize integration.
const inserted = await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' });
console.log('inserted', inserted.insertedId);
For more information, see the Client reference.
Add vectorize to a column:
VectorServiceOptions options = new VectorServiceOptions()
.modelName("text-embedding-3-small")
.provider("openai")
.authentication(Map.of("providerKey", "ASTRA_KMS_API_KEY_NAME"));
AlterTableAddVectorize addVectorize =
new AlterTableAddVectorize()
.columns(Map.of("m_vector", options));
myTable1.alter(addVectorize);
Parameters:
Name | Type | Summary |
---|---|---|
|
Defines an operation to alter a table by adding a vectorize integration to one or more |
|
|
Specialization of the operation, such as |
|
|
|
Optional new type for the row object.
If not provided, the default is |
Returns:
Table<T> - An instance for interacting with the current table where T
represents a Row
.
Alter operations can change the row definition in a table.
However, when adding or dropping vectorize integrations, the pre-existing Table
object should remain largely unchanged.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.core.vectorize.VectorServiceOptions;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.commands.AlterTableAddVectorize;
import com.datastax.astra.client.tables.definition.rows.Row;
import java.util.Map;
public class AlterTableAddVectorizes {
public static void main(String[] args) {
// Database db = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
Table<Row> myTable1 = db.getTable("games");
AlterTableAddVectorize addVectorize =
new AlterTableAddVectorize().columns(
Map.of("m_vector", new VectorServiceOptions()
.modelName("text-embedding-3-small")
.provider("openai").authentication(
Map.of("providerKey", "ASTRA_KMS_API_KEY_NAME")
))
);
myTable1.alter(addVectorize);
}
}
Add a vectorize embedding provider integration to an existing vector
column:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE/ASTRA_DB_TABLE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"addVectorize": {
"columns": {
"VECTOR_COLUMN_NAME": {
"type": "vector",
"dimension": NUM_DIMENSIONS,
"service": {
"provider": "EMBEDDINGS_PROVIDER_NAME",
"modelName": "MODEL_NAME"
}
}
}
}
}
}
}' | jq
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to modify the configuration of a table in a Serverless (Vector) database. It acts as a container for all the attributes and settings required to modify the table. |
|
|
Specifies that you want to add a vectorize integration to an existing |
|
|
Provide the name of the target
|
Returns:
A successful request returns 200 OK
.
Example response
{
"status": {
"ok": 1
}
}
Example:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace/students" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"addVectorize": {
"columns": {
"embedding": {
"type": "vector",
"dimension": 1024,
"service": {
"provider": "mistral",
"modelName": "mistral-embed",
"authentication": {
"providerKey": "mistral-api-key"
}
}
}
}
}
}
}
}' | jq
Remove vectorize from columns
Remove a vectorize embedding provider integration from a vector
column.
You can modify multiple vector
columns in a single request.
This operation doesn’t remove the embeddings stored in the column.
The column becomes a normal |
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Remove vectorize from a column:
new_table = my_table.alter(
AlterTableDropVectorize(columns=["m_vector"]),
)
Parameters:
Name | Type | Summary |
---|---|---|
|
|
An instance of |
|
|
DataStax does not recommend using |
|
|
A timeout, in milliseconds, to impose on the underlying API request.
If not provided, the |
Returns:
Table
- A new table object that is only useful for type-hints purposes.
Do not use the new Table
instance.
Instead, continue to use the original Table
instance for this table.
Example response
The following example response is reformatted for clarity:
Table(
name="COLLECTION_NAME",
keyspace="default_keyspace",
database.api_endpoint="ASTRA_DB_API_ENDPOINT",
api_options=FullAPIOptions(
token=StaticTokenProvider(APPLICATION_TOKEN),
...
),
...
)
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
from astrapy.constants import SortMode
from astrapy.info import (
CreateTableDefinition,
ColumnType,
)
my_table = database.create_table(
"games",
definition=(
CreateTableDefinition.builder()
.add_column("match_id", ColumnType.TEXT)
.add_column("round", ColumnType.TINYINT)
.add_vector_column("m_vector", dimension=3)
.add_column("score", ColumnType.INT)
.add_column("when", ColumnType.TIMESTAMP)
.add_column("winner", ColumnType.TEXT)
.add_set_column("fighters", ColumnType.UUID)
.add_partition_by(["match_id"])
.add_partition_sort({"round": SortMode.ASCENDING})
.build()
),
)
from astrapy.info import AlterTableAddVectorize, VectorServiceOptions
new_table = my_table.alter(
AlterTableAddVectorize(
columns={
"m_vector": VectorServiceOptions(
provider="openai",
model_name="text-embedding-3-small",
authentication={
"providerKey": "ASTRA_KMS_API_KEY_NAME",
},
),
},
),
)
from astrapy.info import AlterTableDropVectorize
# Drop vectorize from a (vector) column
new_table = my_table.alter(
AlterTableDropVectorize(columns=["m_vector"]),
)
For more information, see the Client reference.
Remove vectorize from a table column:
const newTable = await table.alter({
operation: {
dropVectorize: {
columns: ['mVector'],
},
},
});
Parameters:
Name | Type | Summary |
---|---|---|
|
|
Defines an operation to alter a table by dropping a vectorize integration from one or more |
|
|
The client-side timeout for this operation. |
Options (DropVectorizeOperation
):
Name | Type | Summary |
---|---|---|
|
|
The names of the columns from which to remove vectorize information. |
Returns:
Promise<Table<Schema>>
- A promise which resolves to the Table
object after the alter operation is complete.
Example:
Full script
import { CreateTableDefinition, DataAPIClient, InferTablePrimaryKey, InferTableSchema } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
// Infer the table type from the table definition.
// For information about table typing, see the documentation for create table.
type TableSchema = InferTableSchema<typeof TableDefinition>;
// The following script demonstrates all alter operations: add, drop, addVectorize, dropVectorize.
// This example also inserts rows to demonstrate the goal and outcome of each alter operation.
// You can only run one alter operation at a time, but you can have multiple operations in the same script.
(async function () {
// Create a table or error if a 'games' table already exists.
const table = await db.createTable<TableSchema>('games', { definition: TableDefinition });
// Represents the new schema of the table after the alter to add columns
type NewSchema = TableSchema & {
tieBreak: boolean;
venue: string;
}
// @ts-expect-error
// Try to insert data into nonexistent columns.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
// Columns are defined in the same way that you define them in createTable, including name, type, and other properties.
const altered = await table.alter<NewSchema>({
operation: {
add: {
columns: {
tieBreak: 'boolean',
venue: 'text',
},
},
},
});
// Attempt to insert the rows again.
// This should succeed now that all columns exist in the table.
const inserted = await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' });
console.log('inserted', inserted.insertedId);
// Represents the new schema of the table after the alter to drop columns
type NewSchema = Omit<TableSchema, 'tieBreak' | 'venue'>
// Provide the new type of the table as it would be after the alter.
// Note that this just returns the same Table
object, but re-casted as the proper type.
const altered = await table.alter<NewSchema>({
operation: {
drop: {
columns: ['tieBreak', 'venue'],
},
},
});
// @ts-expect-error
// Try to insert data into the removed columns.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, tieBreak: true, venue: 'Thunderdome' })
.catch(e => console.error(e.message));
// @ts-expect-error
// Try to use vectorize on a vector column that doesn't have a vectorize integration.
// This should error both statically and at runtime.
await table.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Add the OpenAI embedding provider integration to the vector column.
const altered = await table.alter({
operation: {
addVectorize: {
columns: {
mVector: {
provider: 'openai',
modelName: 'text-embedding-3-small',
authentication: {
providerKey: 'ASTRA_KMS_API_KEY_NAME',
},
},
},
},
},
});
// Attempt to insert the row again.
// This should succeed now that the vector column has a vectorize integration.
const inserted = await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' });
console.log('inserted', inserted.insertedId);
// Remove vectorize from the specified vector column
const altered = await table.alter({
operation: {
dropVectorize: {
columns: ['mVector'],
},
},
});
// @ts-expect-error
// Try to use vectorize on the vector column that no longer has a vectorize integration.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
// Remove vectorize from the specified vector column
const altered = await table.alter({
operation: {
dropVectorize: {
columns: ['mVector'],
},
},
});
// @ts-expect-error
// Try to use vectorize on the vector column that no longer has a vectorize integration.
// This should error both statically and at runtime.
await altered.insertOne({ matchId: '1', round: 1, mVector: 'The ☀️, The 🌙, The 🌟' })
.catch(e => console.error(e.message));
For more information, see the Client reference.
Remove vectorize from a column:
AlterTableDropVectorize dropVectorize =
new AlterTableDropVectorize("m_vector");
myTable1.alter(dropVectorize);
Parameters:
Name | Type | Summary |
---|---|---|
|
Defines an operation to alter a table by dropping a vectorize integration from one or more |
|
|
Specialization of the operation, including |
|
|
|
Optional new type for the row object.
If not provided, the default is |
Returns:
Table<T> - An instance for interacting with the current table where T
represents a Row
.
Alter operations can change the row definition in a table.
However, when adding or dropping vectorize integrations, the pre-existing Table
object should remain largely unchanged.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.commands.AlterTableDropColumns;
import com.datastax.astra.client.tables.commands.AlterTableDropVectorize;
import com.datastax.astra.client.tables.definition.rows.Row;
public class AlterTableDropVectorizes {
public static void main(String[] args) {
// Database db = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
Table<Row> myTable1 = db.getTable("games");
// Add A Columns
AlterTableDropVectorize dropVectorize = new AlterTableDropVectorize("m_vector");
myTable1.alter(dropVectorize);
}
}
Remove an embedding provider integration from a vector
column:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE/ASTRA_DB_TABLE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"dropVectorize": {
"columns": [ "VECTOR_COLUMN_NAME" ]
}
}
}
}' | jq
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to modify the configuration of a table in a Serverless (Vector) database. It acts as a container for all the attributes and settings required to modify the table. |
|
|
Specify that you want to remove a vectorize integration from a |
|
|
The name of the |
Returns:
A successful request returns 200 OK
.
Example response
{
"status": {
"ok": 1
}
}
Example:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace/students" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"alterTable": {
"operation": {
"dropVectorize": {
"columns": [ "embedding" ]
}
}
}
}' | jq
List table metadata
Get information about the tables in a specific keyspace.
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Get information about the tables in the database’s working keyspace:
database.list_tables()
Get information about tables in a specific keyspace:
database.list_tables(keyspace="KEYSPACE_NAME")
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The keyspace to be inspected. If not specified, the database’s working keyspace is used. |
|
|
A timeout, in milliseconds, for the underlying HTTP request.
If not provided, the |
Returns:
List[ListTableDescriptor]
- A list of ListTableDescriptor
objects in no particular order.
Example response
The following example response is reformatted for clarity:
[
BaseTableDescriptor(
name='fighters',
definition=BaseTableDefinition(
columns=[fighter_id,age,name,nationality,skill_levels],
primary_key=TablePrimaryKeyDescriptor[(fighter_id)]
),
raw_descriptor=...
),
BaseTableDescriptor(
name='games',
definition=BaseTableDefinition(
columns=[match_id,round,fighters,m_vector,score,when,winner],
primary_key=TablePrimaryKeyDescriptor[(match_id)round:a]
),
raw_descriptor=...
)
]
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
tables = my_database.list_tables()
tables
# [BaseTableDescriptor(name='fighters', definition=BaseTableDefinition(...
tables[1].name
# 'games'
tables[1].definition.columns
# {'match_id': TableScalarColumnTypeDescriptor(ColumnType.TEXT),...
tables[1].definition.columns['score']
# TableScalarColumnTypeDescriptor(ColumnType.INT)
tables[1].definition.primary_key.partition_by
# ['match_id']
tables[1].definition.primary_key.partition_sort
# {'round': 1}
For more information, see the Client reference.
Get information about the tables in the database’s working keyspace:
await db.listTables();
Get information about tables in a specified keyspace in the database:
await db.listTables({ keyspace: 'KEYSPACE' });
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The options for this operation. |
Options (ListTablesOptions
):
Name | Type | Summary |
---|---|---|
|
|
If false or undefined, the response includes table names and metadata. If true, the response includes only table names. |
|
|
The keyspace to be inspected. If not specified, the database’s working keyspace is used. |
|
|
The client-side timeout for this operation. |
Returns:
Promise<FullTableInfo[]>
- A promise that resolves to an array of table descriptor objects in no particular order.
Example response
[
{
name: 'games',
definition: {
columns: {
matchId: { type: 'text' },
round: { type: 'tinyint' },
fighters: { type: 'set', valueType: 'uuid' },
mVector: { type: 'vector', dimension: 3 },
score: { type: 'int' },
when: { type: 'timestamp' },
winner: { type: 'text' }
},
primaryKey: {
partitionBy: [ 'matchId' ],
partitionSort: { round: 1 }
}
}
}
]
Example:
import { CreateTableDefinition, DataAPIClient, SomeRow } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
(async function () {
// Create an untyped table if a 'games' table doesn't already exist.
await db.createTable<SomeRow>('games', { definition: TableDefinition, ifNotExists: true });
// Get detailed information about the table.
// Returns information like [{ name: 'games', definition: { ... } }, ...]
await db.listTables().then(console.log);
// Get table names only.
// Returns information like ['games', ...]
await db.listTables({ nameOnly: true }).then(console.log);
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
For more information, see the Client reference.
Get information about tables in the database’s working keyspace:
List<TableDescriptor> tableList = db.listTables();
Get information about tables in a specific keyspace and apply a custom timeout:
ListTablesOptions options = new ListTablesOptions()
.keyspace("KEYSPACE_NAME")
.timeout(Duration.ofSeconds(5));
List<TableDescriptor> tableList2 = database
.listTables(options);
Parameters:
Name | Type | Summary |
---|---|---|
|
Specialization of the operation, including |
Returns:
List<TableDescriptor>
- A list of TableDescriptor
objects in no particular order.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Game;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.TableOptions;
import com.datastax.astra.client.tables.commands.options.ListTablesOptions;
import com.datastax.astra.client.tables.definition.TableDefinition;
import com.datastax.astra.client.tables.definition.TableDescriptor;
import com.datastax.astra.client.tables.definition.rows.Row;
import java.time.Duration;
import java.util.List;
import java.util.Map;
public class ListTables {
public static void main(String[] args) {
// Database astraDb = new DataAPIClient(token).getDatabase(endpoint);
Database db =
DataAPIClients.localDbWithDefaultKeyspace();
// Default
List<TableDescriptor> tableList = db.listTables();
// Options
db.getDatabaseAdmin().createKeyspace("ks2");
ListTablesOptions options = new ListTablesOptions()
.keyspace("ks2")
.timeout(Duration.ofSeconds(5));
List<TableDescriptor> tableList2 = db.listTables(options);
Table<Row> ts = db.getTable("table_simple", new TableOptions().keyspace("ks2"));
// Expecting an error as table does not exist in ks2
}
}
To get table metadata, use listTables
with "explain": true
:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"listTables": {
"options": {
"explain": true
}
}
}' | jq
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to get a list of tables in a keyspace in a Serverless (Vector) database. |
|
|
Whether the response includes table metadata in addition to table names. |
Returns:
A successful response returns a tables
array that contains an object for each table.
If "explain": true
, then each table object contains the table schema, including the table name, column definitions, and primary key.
Example response
{
"status": {
"tables": [
{
"name": "customers",
"definition": {
"columns": {
"order_date": {
"type": "timestamp"
},
"preferences": {
"type": "map",
"keyType": "text",
"valueType": "text"
},
"is_active": {
"type": "boolean"
},
"user_id": {
"type": "uuid"
},
"name": {
"type": "text"
},
"login_attempts": {
"type": "set",
"valueType": "int"
},
"photo": {
"type": "blob"
},
"salary": {
"type": "decimal"
},
"order_id": {
"type": "uuid"
},
"age": {
"type": "int"
},
"tags": {
"type": "list",
"valueType": "text"
}
},
"primaryKey": {
"partitionBy": [
"user_id"
],
"partitionSort": {
"order_id": 1,
"order_date": -1
}
}
}
}
]
}
}
List table names
Get the names of the tables in a specific keyspace as a list of strings.
For the clients, unless otherwise specified, this implementation refers to the tables in the database’s working keyspace.
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Get the names of tables in the database’s working keyspace:
database.list_table_names()
Get the names of tables in a specific keyspace in the database:
database.list_table_names(keyspace="KEYSPACE_NAME")
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The keyspace to be inspected. If not specified, the database’s working keyspace is used. |
|
|
A timeout, in milliseconds, for the underlying HTTP request.
If not provided, the |
Returns:
List[str]
- A list of the table names in no particular order.
Example response
['fighters', 'games']
Example:
from astrapy import DataAPIClient
client = DataAPIClient("TOKEN")
database = client.get_database("API_ENDPOINT")
database.list_table_names()
# ['fighters', 'games']
For more information, see the Client reference.
Get the names of tables in the database’s working keyspace:
await db.listTables({ nameOnly: true });
Get the names of tables in a specific keyspace in the database:
await db.listTables({ nameOnly: true, keyspace: 'KEYSPACE' });
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The options for this operation. |
Options (ListTablesOptions
):
Name | Type | Summary |
---|---|---|
|
|
If false or undefined, the response includes table names and metadata. If true, the response includes only table names. |
|
|
The keyspace to be inspected. If not specified, the database’s working keyspace is used. |
|
|
The client-side timeout for this operation. |
Returns:
Promise<string[]>
- A promise that resolves to an array of all the table names in the keyspace.
Example response
['games']
Example:
import { CreateTableDefinition, DataAPIClient, SomeRow } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
(async function () {
// Create an untyped table if a 'games' table doesn't already exist.
await db.createTable<SomeRow>('games', { definition: TableDefinition, ifNotExists: true });
// Get detailed information about the table.
// Returns information like [{ name: 'games', definition: { ... } }, ...]
await db.listTables().then(console.log);
// Get table names only.
// Returns information like ['games', ...]
await db.listTables({ nameOnly: true }).then(console.log);
// Uncomment the following line to drop the table and any related indexes.
// await table.drop();
})();
For more information, see the Client reference.
Get the name of tables in the database’s working keyspace:
List<String> tableNames = db.listTableNames();
Get the names of tables in a specific keyspace in the database and pass a custom timeout:
ListTablesOptions options = new ListTablesOptions()
.keyspace("ks2")
.timeout(Duration.ofSeconds(5));
List<String> tableList2 = database
.listTableNames(options);
Parameters:
Name | Type | Summary |
---|---|---|
|
Specialization of the operation, including |
Returns:
List<String>
- A list of String
, each representing a table name.
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.TableOptions;
import com.datastax.astra.client.tables.commands.options.ListTablesOptions;
import com.datastax.astra.client.tables.definition.TableDescriptor;
import com.datastax.astra.client.tables.definition.rows.Row;
import java.time.Duration;
import java.util.List;
public class ListTablesNames {
public static void main(String[] args) {
// Database astraDb = new DataAPIClient(token).getDatabase(endpoint);
Database db =
DataAPIClients.localDbWithDefaultKeyspace();
// Default
List<String> tableNames = db.listTableNames();
// Options
db.getDatabaseAdmin().createKeyspace("ks2");
ListTablesOptions options = new ListTablesOptions()
.keyspace("ks2")
.timeout(Duration.ofSeconds(5));
List<String> tableList2 = db.listTableNames(options);
}
}
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"listTables": {
"options": {
"explain": false
}
}
}' | jq
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to get a list of tables in a keyspace in a Serverless (Vector) database. |
|
|
If true, the response includes table names and metadata. If false or unset, the response includes only table names. |
Returns:
If "explain": false
, a successful response returns a array of table names.
Example response
{
"status": {
"tables": [
"table_name_1",
"table_name_2"
]
}
}
Drop a table
Delete a table from a database, including all associated indexes and data stored in the table.
Attempting to use the table
object after dropping the table returns an API error because it references a non-existent table.
-
Python
-
TypeScript
-
Java
-
curl
For more information, see the Client reference.
Drop a table by name:
database.drop_table("fighters")
Drop a table through a Table
object:
my_table.drop()
Drop a table passing a Table
to a Database
:
database.drop_table(my_table)
Parameters:
Name | Type | Summary |
---|---|---|
|
|
Either the name of a table or a |
|
|
If If |
|
|
A timeout, in milliseconds, for the underlying schema-changing HTTP request.
If not provided, the |
Example:
database.list_table_names()
# ['fighters', 'games']
database.drop_table("fighters")
database.list_table_names()
# ['games']
# not erroring because of if_exists:
database.drop_table("fighters", if_exists=True)
For more information, see the Client reference.
Drop a table by name in the database’s working keyspace:
await db.dropTable('TABLE_NAME');
Drop a table by name in a specific keyspace:
await db.dropTable('TABLE_NAME', { keyspace: 'KEYSPACE' });
Drop a table through a Table
object:
await table.drop();
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The name of the table to drop, if dropping through a |
|
|
The options for this operation |
Options (DropTableOptions
):
Name | Type | Summary |
---|---|---|
|
|
If If |
|
|
If dropping through a |
|
|
The client-side timeout for this operation. |
Returns:
Promise<void>
- A promise that resolves when the operation is complete.
Example:
import { CreateTableDefinition, DataAPIClient, SomeRow } from '@datastax/astra-db-ts';
// Instantiate the client and connect to the database
const client = new DataAPIClient();
const db = client.db(process.env.CLIENT_DB_URL!, { token: process.env.CLIENT_DB_TOKEN! });
// Create table schema using bespoke Data API table definition syntax.
// For information about table definition and data types, see the documentation for createTable.
const TableDefinition = <const>{
columns: {
matchId: 'text'
round: 'tinyint',
mVector: { type: 'vector', dimension: 3 },
score: 'int',
when: 'timestamp',
winner: 'text',
fighters: { type: 'set', valueType: 'uuid' },
},
primaryKey: {
partitionBy: ['matchId'],
partitionSort: { round: 1 },
},
} satisfies CreateTableDefinition;
(async function () {
// Create an untyped table or error if a 'games' table already exists.
const table = await db.createTable<SomeRow>('games', { definition: TableDefinition });
// Drop a table from a database's working keyspace without checking if the table exists.
// If there is no match, the command succeeds but does nothing.
// If there is a match, the named table is deleted.
await db.dropTable(table.name);
// Use a Table object to run dropTable without checking if the table exists.
await table.drop();
// Use a Table object to drop a table only if the table exists.
// Errors if there is no match.
await table.drop({ ifExists: true });
})();
For more information, see the Client reference.
Drop a table by name in the database’s working keyspace:
database.dropTable("fighters");
Drop a table through a Table
object:
myTable.drop();
Drop a table through a database
instance with options:
DropTableOptions options = new DropTableOptions()
.ifExists(false)
.timeout(ofSeconds(5));
database.dropTable("games", options);
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The name of the table to drop, if dropping through a |
|
Specialization of the operation:
|
Example:
package com.datastax.astra.client.database;
import com.datastax.astra.client.DataAPIClients;
import com.datastax.astra.client.core.auth.EmbeddingAPIKeyHeaderProvider;
import com.datastax.astra.client.databases.Database;
import com.datastax.astra.client.tables.Game;
import com.datastax.astra.client.tables.Table;
import com.datastax.astra.client.tables.TableOptions;
import com.datastax.astra.client.tables.commands.options.CreateTableOptions;
import com.datastax.astra.client.tables.commands.options.DropTableOptions;
import com.datastax.astra.client.tables.definition.TableDefinition;
import com.datastax.astra.client.tables.definition.columns.ColumnDefinitionVector;
import com.datastax.astra.client.tables.definition.columns.ColumnTypes;
import com.datastax.astra.client.tables.definition.rows.Row;
import static com.datastax.astra.client.core.query.Sort.ascending;
import static com.datastax.astra.client.core.vector.SimilarityMetric.COSINE;
import static java.time.Duration.ofSeconds;
public class DropTable {
public static void main(String[] args) {
// Database astraDb = new DataAPIClient(token).getDatabase(endpoint);
Database db = DataAPIClients.localDbWithDefaultKeyspace();
// Drop without options
db.dropTable("games");
// Adding a timestamp
DropTableOptions options = new DropTableOptions()
.ifExists(false)
.timeout(ofSeconds(5));
db.dropTable("games", options);
}
}
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/ASTRA_DB_KEYSPACE" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"dropTable": {
"name": "TABLE_NAME"
}
}'
Parameters:
Name | Type | Summary |
---|---|---|
|
|
The Data API command to delete a table in a Serverless (Vector) database. It acts as a container for all the attributes and settings required to delete the table. |
|
|
The name of the table to delete. |
Returns:
A successful request returns 200 OK
.
Example response
{
"status": {
"ok": 1
}
}
Example:
curl -sS --location -X POST "ASTRA_DB_API_ENDPOINT/api/json/v1/default_keyspace" \
--header "Token: ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"dropTable": {
"name": "students"
}
}'