TypeCQL

About TypeCQL

TypeCQL - An ORM for CQL databases, supporting Cassandra and ScyllaDB with CQL v3.

Download TypeCQL with npm.

TypeCQL offers you:

  • Built-in mapper with custom columns and options
  • Excellent type system (With TypeScript 5+)
  • Queries optimization
  • Multiple connections support
  • Advanced methods
  • Automatic loading of tables, columns
  • Tool for migrations
  • Transactions
  • Supports both NestJS and typescript Node.js
  • Entities
  • Very easy installation and usage

Under the hood uses a DataStax cassandra-driver.

Patch Notes

You can check all patch notes here.

Installation with NestJS

Here are some steps to install:
  1. Install the package via npm
  2. npm install typecql@latest
  3. Register your database connection (for example in app.module)
  4. Sync version with options:

    import { RootOptions, TypeCQLModule } from 'typecql';
    
    TypeCQLModule.forRoot({
          contactPoints: ['cp1', 'cp2'],
          keyspace: 'test_keyspace',
          localDataCenter: 'datacenter1',
          credentials: {
              username: 'user',
              password: 'pass',
          }
        })

    You can find more options here.

    Async version with options:

    import { RootOptions, TypeCQLModule } from 'typecql';
    
    TypeCQLModule.forRootAsync({
          useFactory: (configService: ConfigService) => {
            const options: RootOptions = {
              contactPoints: [process.env.CONTACT1, process.env.CONTACT2],
              keyspace: process.env.KS,
              localDataCenter: process.env.LDC,
              credentials: {
                username: process.env.USERNAME,
                password: process.env.PASSWORD
              },
              camelCaseEnabled: true,
            };
            return options;
          },
          inject: ['CONFIG_SERVICE'],
        })
  5. Create entity classes with provided metadata decorators. See Entities and Metadata.
  6. Register repositories in any other module where you want to use these entities.

    TypeCQLModule.forFeature([Users, Carts])
  7. Finally, inject the client and/or repository:

    import { BaseRepository, InjectClient, InjectRepository } from 'typecql';
    import { Client } from 'typecql';
    // OR
    import { Client } from 'cassandra-driver';
    //...
    constructor(
        @InjectClient() private readonly client: Client,
        @InjectRepository(User) private readonly repository: BaseRepository<User>,
      ) {}
  8. Now you can use repository and client methods.

Installation with NestJS with multiple clients

Here are some steps to install:
  1. Install the package via npm
  2. npm install typecql@latest
  3. Register your database connection (for example in app.module)
  4. Sync version with options:

    import { RootOptions, TypeCQLModule } from 'typecql';
    
    TypeCQLModule.forRoot({
          contactPoints: ['cp1', 'cp2'],
          keyspace: 'test_keyspace',
          // For sync version, put connectionName here:
          connectionName: 'connection1',
          localDataCenter: 'datacenter1',
          credentials: {
              username: 'user',
              password: 'pass',
          }
        })
    TypeCQLModule.forRoot({
          contactPoints: ['cp1', 'cp2'],
          keyspace: 'test_keyspace_second',
          // For sync version, put connectionName here:
          connectionName: 'connection2',
          localDataCenter: 'datacenter1',
          credentials: {
              username: 'user',
              password: 'pass',
          }
        })        

    You must provide unique connection name for each connection.

    Option "camelCaseEnabled" will be its own for each connection, keep it in mind.

    You can find more options here.

    Async version with options:

    import { RootOptions, TypeCQLModule } from 'typecql';
    
    TypeCQLModule.forRootAsync({
          // For ASYNC version, put connectionName here:
          connectionName: 'connection1',
          useFactory: (configService: ConfigService) => {
            const options: RootOptions = {
              contactPoints: [process.env.CONTACT1, process.env.CONTACT2],
              keyspace: process.env.KS,
              localDataCenter: process.env.LDC,
              credentials: {
                username: process.env.USERNAME,
                password: process.env.PASSWORD
              },
              camelCaseEnabled: true,
            };
            return options;
          },
          inject: ['CONFIG_SERVICE'],
        })
    TypeCQLModule.forRootAsync({
          // For ASYNC version, put connectionName here:
          connectionName: 'connection2',
          useFactory: (configService: ConfigService) => {
            const options: RootOptions = {
              contactPoints: [process.env.CONTACT1, process.env.CONTACT2],
              keyspace: process.env.KS,
              localDataCenter: process.env.LDC,
              credentials: {
                username: process.env.USERNAME,
                password: process.env.PASSWORD
              },
              camelCaseEnabled: true,
            };
            return options;
          },
          inject: ['CONFIG_SERVICE'],
        })        
    For async version you must provide connection name not inside useFactory, only in options.
  5. Create entity classes with provided metadata decorators. See Entities and Metadata.
  6. Register repositories with provided connection names in any other module where you want to use these entities.

    TypeCQLModule.forFeature([Users], 'connection1');
    TypeCQLModule.forFeature([Carts, Wallets], 'connection2');
  7. Finally, choose and inject the client and/or repository with provided connection name:

    import { BaseRepository, InjectClient, InjectRepository } from 'typecql';
    import { Client } from 'typecql';
    // OR
    import { Client } from 'cassandra-driver';
    //...
    constructor(
        @InjectClient('connection1') private readonly client: Client,
        @InjectRepository(User, 'connection1') private readonly repository: BaseRepository<User>,
      ) {}
  8. Now you can use repository and client methods.

Providing connection names allowed only when multiple connections registered, for single client usage, see.

Installation with TypeScript

Here are some steps to install:
  1. Install the package via npm
  2. npm install typecql@latest
  3. Create connection with client options:
  4. import { RootOptions, TypeCQLModule } from 'typecql';
    
    const client = await TypeCQLModule.createClient({
      contactPoints: ['localhost'],
      keyspace: 'playground',
      localDataCenter: 'datacenter1',
      credentials: {
        username: 'cassandra',
        password: 'cassandra',
      },
      camelCaseEnabled: true,
    })

    You can find more options here.

  5. Create entity classes with provided metadata decorators Check this paragraph here: Entities and Metadata.
  6. Create repositories.

    const usersRepository = TypeCQLModule.getRepository(Users);
    const cartsRepository = TypeCQLModule.getRepository(Carts);
    
  7. Now you can use repository and client methods.

Installation with TypeScript with multiple connections

Here are some steps to install:
  1. Install the package via npm
  2. npm install typecql@latest
  3. Create connection with client options:
  4. import { RootOptions, TypeCQLModule } from 'typecql';
    
    const client1 = await TypeCQLModule.createClient({
      contactPoints: ['localhost'],
      keyspace: 'playground',
      // Put connectionName here:
      connectionName: 'connection1',
      localDataCenter: 'datacenter1',
      credentials: {
        username: 'cassandra',
        password: 'cassandra',
      },
      camelCaseEnabled: true,
    })
    const client2 = await TypeCQLModule.createClient({
      contactPoints: ['localhost'],
      keyspace: 'playground',
      // Put connectionName here:
      connectionName: 'connection2',
      localDataCenter: 'datacenter1',
      credentials: {
        username: 'cassandra',
        password: 'cassandra',
      },
      camelCaseEnabled: true,
    })
    You must provide unique connection name for each connection.

    Option "camelCaseEnabled" will be its own for each connection, keep it in mind.

    You can find more options here.

  5. Create entity classes with provided metadata decorators Check this paragraph here: Entities and Metadata.
  6. Create repositories with connection names provided:

    const usersRepository = TypeCQLModule.getRepository(Users, 'connection1');
    const cartsRepository = TypeCQLModule.getRepository(Carts, 'connection2');
    
    You must provide connection name only while using multiple connections. For single usage, see.
  7. Now you can use repositories and clients methods.

Entities and Metadata

This paragraph is about preparing Entities with metadata.

  1. Create new class, for example Users, create some fields, and extend it from TypeCQL Entity.
    // users.entity.ts
    import { Entity } from 'typecql';
    
    export class Users extends Entity {
      id: string;
    
      money: number;
    
      age: number;
    }
    
  2. Use @Table decorator at class definition.

    @Table('name', options)
    Decorator parameters:
    Name Values Example Description
    name Any string Test If provided, this string will be used as table name.
    options clusteringKeys Array of strings or string with clustering keys ['test', ['first', 'second']] or quoted, ['"test"', ['"first"', '"second"']] If provided, field will be used when auto table creation is enabled instead of under the hood logic.
    primaryKeys Array of strings or string with primary keys ['test', ['first', 'second']] or quoted, ['"test"', ['"first"', '"second"']] If provided, field will be used when auto table creation is enabled instead of under the hood logic.
    ordering Array of objects with key name and direction [{key: 'test', direction: 'ASC'}, {key: 'age', direction: 'DESC'}] or quoted, [{key: '"test"', direction: 'ASC'}] If provided, field will be used when auto table creation is enabled instead of under the hood logic.
    additionalQuery String with part of query. " AND COMPRESSION = {'sstable_compression': ''}" and e.g. If provided, this part of query will be added to table creation process.
  3. Use @PrimaryKey decorator for PK`s - clustering and partitioning.

    @PrimaryKey(options)
    Decorator parameters:
    Name Values Description
    field Any string If provided, this string will be used as column name.
    type One of CQL types If provided, field will be used for auto table and column creation. Type 'uuid' will automatically generate valid uuid string.
    default Primitive, object or function Default value of column - using in insert or update.
    primaryKeyType 'partition' or 'cluster' If provided, column will be used in table creation.
  4. Use @Column decorator for static columns.

    @Column(options)
    Decorator parameters:
    Name Values Description
    field Any string If provided, this string will be used as column name.
    type One of CQL types If provided, field will be used for auto table and column creation.
    default Primitive, object or function Default value of column - using in insert or update.
  5. After those steps we will get something like this:
    // users.entity.ts
    import { Entity } from 'typecql';
    
    @Table('users')
    export class Users extends Entity {
      @PrimaryKey({ type: 'uuid', primaryKeyType: 'partition' })
      id: string;
    
      @Column({ type: 'int', default: 150_000, field: 'wallet' })
      money: number;
    
      @PrimaryKey({ type: 'int', primaryKeyType: 'cluster' })
      age: number;
    }

Entities methods

Entities instances have two methods: save and delete.

Save

Usage: .save() method could be used for updating some fields for row in database.
const entity = await repository.findOne(...);
entity.testProp = 123;
await entity.save();
console.log(entity.testProp) // 123
Default values works in these methods.
All primary keys must be provided or defaulted.

Create

Usage: .create() method could be used for creating new entity in database.
Using raw new MyEntity() methods should be avoided in multiple connections build.

Its always better to get instance from .find*() and .insert() methods of repositories.

const newEntity = new Entity();
entity.pk = 123;
entity.someKey = true;

await entity.create();
console.log(entity.pk) // 123
console.log(entity.someKey) // true
Default values works in these methods.
All primary keys must be provided.

Delete

Usage: .delete() method could be used for deleting row from database.
const entity = await repository.findOne(...);
await entity.delete();
// Now, there is no row with this data in database
All primary keys must be provided.

Client options

TypeCQL client includes both cassandra-driver and TypeCQL options:
Name Values Description
Cassandra-driver options
connectionName string (default: 'default') Should be provided in sync NestJS and TypeScript registration of clients.
camelCaseEnabled boolean (default: false) If provided, fields from entities without default field will be transferred to camelCase in queries.

If false, underscoring will be used.

autoCreateTables boolean (default: false) If provided, new table will be created if not exists with metadata.
autoCreateColumns boolean (default: false) If provided, new columns will be created if not exists with metadata.

Auto loading

TypeCQL supports 2 cases of auto loading: loading tables and columns.

  • Table loading: TypeCQL will gather metadata from entities and provided in @Table decorator options.

    In the table creation only will be used fields with type parameter.

    Options in @Table decorator will override default loading logic.

  • Column loading: TypeCQL will gather metadata from entities and provided in @Column decorator options.

    In the column creation only will be used fields with type parameter.

    Only static columns (i.e. not primaries) will be added.

    Column loading will not change existing columns, use migrations instead.

Migrations

TypeCQL provides easy and smart migration system.

There is basic migration flow:

  1. create config file in your project with exact name: typecql.config.ts with the following structure:
  2. export const config: RootOptions = {
      contactPoints: ['localhost'],
      keyspace: 'testKS',
      localDataCenter: 'datacenter1',
      credentials: {
        username: 'username',
        password: 'password',
      },
      //... and other options
    };
    
  3. Then, create folder "migrations" in project.
  4. Create file in "migrations" and its subfolders with any .ts name and follow this code:
    import { TypeCQLMigration } from 'typecql';
    import { Client } from 'cassandra-driver';
    
    export class MigrationName1234 extends TypeCQLMigration {
      public async up(client: Client) {
        await client.execute(
          'CREATE TABLE IF NOT EXISTS test (name text, id uuid PRIMARY KEY)',
        );
      }
      public async down(client: Client) {
        await client.execute(
          'DROP TABLE test',
        );
      }
    }

    TypeCQL will find migration files by itself.

    It's better to provide both UP and DOWN methods, but otherwise, functionality will not break.

    CAUTION: Migrations executing in ascending order by number in class name.

    On "UP" migration AddTable123 will be executed before SomeMigration1000

    On "DOWN" migration AddTable123 will be executed after SomeMigration1000

  5. Then, you will need to build your project with npm.
  6. Add two scripts to your package.json file like that:
    "scripts": {
        //...
        "your_command1": "migrate-up",
        "your_command2": "migrate-down"
      },
  7. Finally, run those commands when you need.

Transactions

TypeCQL uses logged batches as transactions, and here how to use them:

  1. Use any of registered repository.
  2. Call .createTransaction() of repository.
    const transaction = this.repository.createTransaction();
  3. Get tables from transaction.of(User) to get its own query builder and use update, insert and delete statements.
Here`s an example:
// Create an transaction
const transaction = this.repository.createTransaction();
// Select entity with .of(...) and call and create method, all default values will be created
const newUser = transaction.of(User).create({ balance: 0 }, { returning: true });
// Use another entity table
transaction.of(Cart).create({ userId: newUser.id }, { returning: true });
// Update example of Cart entity
transaction.of(Cart).update({ where: { userId: newUser.id } }, { isFirstBuy: true });
// Delete some entities
transaction.of(Cart).delete({ where: { userId: newUser.id }, if: { isFirstBuy: false } });

await transaction.executeTransaction(); // (optional) consistencies.all or one of any.
function greet(name: string): string {
    return "Hello, " + name + "!";
}
console.log(greet("World"));

Use if statements carefully: one negative statement will fail an entire transaction!

Only insert, update and delete statements can be executed!

Insert method in transactions support options with returning (default: false) flag, returns new entity with chosen and default parameters.

Methods: Insert

You can see all TypeCQL insert queries methods in sections below.

You can look information about insert queries here.

insert

Briefing

Insert is an async method that takes options object and data parameter as object or array of objects with entity type.

Method result depends on options provided.
Restriction: INSERT does not support IF NOT EXISTS and USING TIMESTAMP in the same statement.
Restriction: batch option does not work with replace: false.
Do not use replace: false with large amount of data - Paxos protocol has bad performance.

Usages

BaseRepository<Entity>
        .insert(
            data: InsertParams<Test>[] | InsertParams<Test>,
            options?: {returning?: boolean, returnRaw?: boolean, replace?: boolean, batch?: boolean, ttl?: number, timestamp?: number, consistency?: consistencies }
          ): Promise<InsertReturn<T>>

Parameters

Name Type Required Example Description
data Entity | Array<Entity> X { id: 'id', age: 55 }

or

[ { id: 'id1' }, { id: 'id2' } ]

If and array were provided, method will return Array of Entities. Otherwise, single Entity instance. Depends on options.
options returning boolean

(default: false)

returning: true If true, TypeCQL will return entity(ies).

Otherwise, will return void value.

returnRaw boolean

(default: false)

returnRaw: true If true, TypeCQL will return Array of Instances or Instance, instead of { wasApplied: boolean, row(s): Instance(s) }.

replace boolean

(default: true)

replace: true If true, TypeCQL will always change data.

Otherwise, it will fetch data at first, and then if no data fetched, insert and(or) return existing data.

Do not use replace: false with large amount of data - Paxos protocol has bad performance.

batch boolean

(default: false)

batch: true If true, batch will be used instead of individual requests. Using for atomicity and better performance.
ttl number

(default: undefined)

ttl: 86400 If number provided, ttl will be set to query(ies).
timestamp number

(default: undefined)

timestamp: 1715774605 If number provided, timestamp will be set to query(ies).

Be careful while using this option.

allowFiltering boolean

(default: false)

false If true, allow filtering will be used with query. Do not work outside of development DB stands.
consistency enum

(default: undefined)

consistencies.all Used for providing consistency level for query(ies).

Result list

Results
Entity
Array<Entity>
{ wasApplied: boolean }
{ wasApplied: boolean, row: Entity } | { wasApplied: boolean, row: Entity }[]
{ wasApplied: boolean, rows: Entity[] }

Methods: Delete

You can see all TypeCQL delete queries methods in sections below.

You can look information about delete queries here.

delete

Briefing

Delete is an async method that takes where, if and fields parameters and executes delete query.

The method returns { wasApplied: boolean } in all cases.
DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns.

Usages

BaseRepository<Entity>
        .delete(parameters: deleteParameters<Entity>): Promise<DeleteReturn>

Parameters

Name Type Required Example Description
fields Array<keyof Entity>

|

Array<string>

[ 'id', 'age' ]

or

[ 'orders['may']' ]

You can provide keys of entity and any other strings, i.e. map item and so on...

If not provided, whole row will be deleted.

where { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } X where: { id: 'id', age: gte(18) } Takes object of entity any string fields with its values or SpecialWhere values.
if { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } if: { id: 'id', age: IN(18, 20, 30) } Takes object of entity any string fields with its values or SpecialWhere values.

Use carefully with conditional updates.

allowFiltering boolean

(default: false)

false If true, allow filtering will be used with query. Do not work outside of development DB stands.
consistency enum

(default: undefined)

consistencies.all Used for providing consistency level for query(ies).
timestamp number

(default: undefined)

timestamp: 1715774605 If number provided, timestamp will be set to query(ies).

Be careful while using this option.

Result list

Results
{ wasApplied: boolean }*

Methods: Update

You can see all TypeCQL update queries methods in sections below.

You can look information about update queries here.

update

Briefing

Update is an async method that takes where, if and fields parameters and partial object to update and executes update query.

The method returns { wasApplied: boolean } in all cases.
UPDATE statements must restrict all PRIMARY KEY columns with equality relations in order to conditionally update columns.

Usages

BaseRepository<Entity>
        .update(
          parameters: updateParameters<Entity>,
          partialObject: updateObject<Entity>
        ): Promise<UpdateReturn>

Parameters

Name Type Required Example Description
parameters fields Array<keyof Entity>

|

Array<string>

[ 'id', 'age' ]

or

[ 'orders['may']' ]

You can provide keys of entity and any other strings, i.e. map item and so on...

If not provided, whole row will be deleted.

where { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } X where: { id: 'id', age: gte(18) } Takes object of entity any string fields with its values or SpecialWhere values.
if { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } if: { id: 'id', age: IN(18, 20, 30) } Takes object of entity any string fields with its values or SpecialWhere values.

Use carefully with conditional updates.

timestamp number

(default: undefined)

timestamp: 1715774605 If number provided, timestamp will be set to query(ies).

Be careful while using this option.

ttl number

(default: undefined)

ttl: 1233 If number provided, ttl will be set to query(ies).

In Update statements ttl will be applied only on added/updated columns.

allowFiltering boolean

(default: false)

false If true, allow filtering will be used with query. Do not work outside of development DB stands.
consistency enum

(default: undefined)

consistencies.all Used for providing consistency level for query(ies).
partialObject { [K in (keyof Entity | string)]?: Entity[K] | SpecialSet | unknown } X { age: 33, balance: addToCounter(7_000) } Takes object of entity any string fields with its values or SpecialSet values.

Result list

Results
{ wasApplied: boolean }*

Methods: Select

You can see all TypeCQL select queries methods in sections below.

You can look information about select queries here.

findOne

Briefing

FindOne is an async method that takes where, and select with other options parameters and executes select query.

The method returns Entity object or object with selected fields if "select" option provided. If no entities found, null will be returned.

Usages

BaseRepository<Entity>
        .findOne(
          parameters?: {
            select?: SelectFields<Entity>,
            where: WhereFields<Entity>,
            limit?: number,
            page?: number,
            orderBy?: OrderByFields<Entity>,
            allowFiltering?: boolean,
            consistency?: consistencies
          }
        ): Promise<Entity | SelectResult<Entity, select> | null>

Parameters

Name Type Required Example Description
parameters select Array<keyof Entity>

|

Array<string>

[ 'id', 'age' ]

or

[ 'orders['may']' ]

You can provide keys of entity and any other strings, i.e. map item and so on...

If not provided, whole row will be deleted.

where { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } X where: { id: 'id', age: gte(18) } Takes object of entity any string fields with its values or SpecialWhere values.
limit number (default: 500) 100 Takes object of entity any string fields with its values or SpecialWhere values.

Use carefully with conditional updates.

page number 25 If provided, typecql will try to find page results. For example, page 5 with limit 10 will give 41-51 results. Max limit for paging is 500, so if you
orderBy Array<

{ field: string, dir: 'up' | 'down' }

>

(default: false)

[{ field: 'balance', 'up' }, { field: 'orders', 'down' }] This parameters should be used strictly like described here. Orders results by columns and directions.
allowFiltering boolean

(default: false)

false If true, allow filtering will be used with query. Do not work outside of development DB stands.
consistency enum

(default: undefined)

consistencies.all Used for providing consistency level for query(ies).

Result list

Results
null*
Instance of Entity
{ [selected_field_or_alias]: any }*

findMany

Briefing

FindMany is an async method that takes where, and select with other options parameters and executes select query.

The method returns array of Entities or array of object with selected fields if "select" option provided. If no entities found, [] will be returned.

Usages

BaseRepository<Entity>
        .findMany(
          parameters?: {
            select?: SelectFields<Entity>,
            where: WhereFields<Entity>,
            limit?: number,
            page?: number,
            orderBy?: OrderByFields<Entity>,
            allowFiltering?: boolean,
            consistency?: consistencies
          }
        ): Promise<SelectResult<Entity, select>[] | Entity[]>

Parameters

Name Type Required Example Description
parameters select Array<keyof Entity>

|

Array<string>

[ 'id', 'age' ]

or

[ 'orders['may']' ]

You can provide keys of entity and any other strings, i.e. map item and so on...

If not provided, whole row will be deleted.

where { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } X where: { id: 'id', age: gte(18) } Takes object of entity any string fields with its values or SpecialWhere values.
limit number (default: 500) 100 Takes object of entity any string fields with its values or SpecialWhere values.

Use carefully with conditional updates.

page number 25 If provided, typecql will try to find page results. For example, page 5 with limit 10 will give 41-51 results. Max limit for paging is 500, so if you
orderBy Array<

{ field: string, dir: 'up' | 'down' }

>

(default: false)

[{ field: 'balance', 'up' }, { field: 'orders', 'down' }] This parameters should be used strictly like described here. Orders results by columns and directions.
allowFiltering boolean

(default: false)

false If true, allow filtering will be used with query. Do not work outside of development DB stands.
consistency enum

(default: undefined)

consistencies.all Used for providing consistency level for query(ies).

Result list

Results
[]*
Array of Entity instances
Array of { [selected_field_or_alias]: any }*

findAndCount

Briefing

FindAndCount is an async method that takes where, and select with other options parameters and executes select query.

The method returns array of Entities or array of object with selected fields if "select" option provided and count of all entities. If no entities found, {rows: [], count: 0} will be returned.

Usages

BaseRepository<Entity>
        .findAndCount(
          parameters?: {
            select?: SelectFields<Entity>,
            where: WhereFields<Entity>,
            limit?: number,
            page?: number,
            orderBy?: OrderByFields<Entity>,
            allowFiltering?: boolean,
            consistency?: consistencies
          }
        ): Promise<{ rows: SelectResult<T, S>[] | T[]; count: number }>

Parameters

Name Type Required Example Description
parameters select Array<keyof Entity>

|

Array<string>

[ 'id', 'age' ]

or

[ 'orders['may']' ]

You can provide keys of entity and any other strings, i.e. map item and so on...

If not provided, whole row will be deleted.

where { [K in (keyof Entity | string)]?: Entity[K] | SpecialWhere | unknown } X where: { id: 'id', age: gte(18) } Takes object of entity any string fields with its values or SpecialWhere values.
limit number (default: 500) 100 Takes object of entity any string fields with its values or SpecialWhere values.

Use carefully with conditional updates.

page number 25 If provided, typecql will try to find page results. For example, page 5 with limit 10 will give 41-51 results. Max limit for paging is 500, so if you
orderBy Array<

{ field: string, dir: 'up' | 'down' }

>

(default: false)

[{ field: 'balance', 'up' }, { field: 'orders', 'down' }] This parameters should be used strictly like described here. Orders results by columns and directions.
allowFiltering boolean

(default: false)

false If true, allow filtering will be used with query. Do not work outside of development DB stands.
consistency enum

(default: undefined)

consistencies.all Used for providing consistency level for query(ies).

Result list

Results
{ rows: [], count: 0 }*
{ rows: [Entity], count: number }
{ rows: [{ [selected_field_or_alias]: any }], count: number }*

Operators

TypeCQL provides many operators to help with more complicated queries.

Operators: count

Get count value of resolved rows.

Converts to "COUNT(key)".

Use count only in SELECT statements.
In count() you need to provided truly name of column by yourself.

Example

select: [{field: count('id')}]

Operators: max

Get max value of resolved rows.

Converts to "MAX(key)".

In max() you need to provided truly name of column by yourself.

Example

select: [{field: max('balance')}]

Operators: min

Get min value of resolved rows.

Converts to "MIN(key)".

In min() you need to provided truly name of column by yourself.

Example

select: [{field: min('balance')}]

Operators: TOKEN

Get token of column or value.

Converts to "TOKEN(keyOrValue)".

In TOKEN() with key provided, you need to provide truly name of column.
In TOKEN() with value provided, you need to provide correct type of value.

Examples

where: { id: gte(TOKEN('AnotherId')) }
where: { [TOKEN('id')]: gte(TOKEN('AnotherId')) }

Operators: gte

Operator of greater or equal than X

Converts to "key >= value".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.

Example

where: { balance: gte(100_000) }

Operators: gte

Operator of greater than X

Converts to "key > value".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.

Example

where: { balance: gt(50_000) }

Operators: lte

Operator of less or equal than X

Converts to "key <= value".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.

Example

where: { balance: lte(10_000) }

Operators: lt

Operator of less than X

Converts to "key < value".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.

Example

where: { balance: lt(1_000_000) }

Operators: lt

Operator of equal to X

Converts to "key = value".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.

Examples

where: { name: eq('George') }
where: { driver: eq(true) }

Operators: IN

Operator of key IN values

Converts to "key IN (value1, value2)".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.

Examples

where: { name: IN('George', 'John') }
where: { age: IN(20, 21, 22) }

Operators: and

Operator that use all provided operators and use it in query with "AND"

Converts to "key IN (value1, value2)".

Key will be automatically used while building a query.
Could be used in WHERE and IF parts of all statements.
You can provide operators and variables as parameters. Single variables will be recognized and equal to Variable.

Examples

//single variables also can be provided with(or) other operators
where: { brand: and(eq('BMW'), eq('Mercedes-Benz'), 'AUDI') }
where: { manufactureYear: and(lte(2024), gt(1999)) }

Make new operator by yourself!

Operator "literal" allows you to create operators to use in "WHERE" and "IF" statements.

Literals could be prepared and unprepared either.

To use prepared:

1) Provide options object with { prepared: true, preparedValues: array or value }.

2) Use "?" in literals where you would use values.

If you want to provide array in preparedValues - follow this example: preparedValues: [[1,2,3], 'x', true, ...]

Could be used in WHERE and IF parts of all statements.

Examples

// Create unprepared operator
const myLiteral = literal('>= 1000')
// Usage
where: { key: myLiteral }
// Create prepared operator (example for frozen set/list)
// if you need to use and array as value, put it as array in preparedValues Array!
const myPreparedLiteral = (arr: number[]) => literal('= ?', {prepared: true, preparedValues: [arr]})
// Usage
where: { key: myPreparedLiteral([3,6,9]) }

Operators: addToSet

Operator that can be used to add items to set.

Converts to "key = key + {values}".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someSetOne: addToSet('one'),
        someSetSec: addToSet([1, 2, 3, 4, 5]),
      },
    );

Operators: deleteFromSet

Operator that can be used to delete items from set.

Converts to "key = key - {values}".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someSetOne: deleteFromSet('one'),
        someSetSec: deleteFromSet([1]),
      },
    );

Operators: clearSet

Operator that can be used to clear set.

Converts to "key = {}".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someSetOne: clearSet(),
        someSetSec: clearSet(),
      },
    );

Operators: addToList

Operator that can be used to add items to list.

Converts to "key = key + [values]".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someListOne: addToList('one'),
        someListSec: addToList([1, 2, 3, 4, 5]),
      },
    );

Operators: deleteFromList

Operator that can be used to delete items from list.

Converts to "key = key - [values]".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someListOne: deleteFromList('one'),
        someListSec: deleteFromList([1]),
      },
    );

Operators: clearList

Operator that can be used to clear set.

Converts to "key = []".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someListOne: clearList(),
        someListSec: clearList(),
      },
    );

Operators: addToMap

Operator that can be used to add items to map.

Converts to "key = key + {values}".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

// someMap is map<text, boolean>
repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someMap: addToMap({test: true}),
      },
    );

Operators: deleteFromList

Operator that can be used to delete items from map.

Converts to "key = key - {map_keys}".

You need to provide an array of keys or key to delete.
Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someMapOne: deleteFromMap('one'),
        someMapSec: deleteFromMap(['test1', 'test2'])
      },
    );

Operators: clearList

Operator that can be used to clear map.

Converts to "key = {}".

Key will be automatically used while building a query.
Could be used in SET statements.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        someMap: clearMap(),
      },
    );

Operators: increaseCounter

Operator that can be used to increase counter with value.

Converts to "key = key + value".

Key will be automatically used while building a query.
Could be used in SET statements.
Only use with "counter" columns.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        specialTokens: increaseCounter(200),
      },
    );

Operators: decreaseCounter

Operator that can be used to decrease counter with value.

Converts to "key = key - value".

Key will be automatically used while building a query.
Could be used in SET statements.
Only use with "counter" columns.

Example

repository.update(
      {
        where: { id: 'id' },
      },
      {
        balance: 100_000,
        specialTokens: decreaseCounter(100),
      },
    );