3 Collections
Anton Nesterov edited this page 2026-02-23 10:14:25 +01:00

Collections

Collections are the primary way to structure and organize your data in VSKI. Each collection has a schema that defines the fields and their types.

Collections can live in in different databases, but collection metadata is stored in the default database.

Creating Collections

Basic Collection

const collection = await client.settings.collections.create({
  name: "posts",
  type: "base",
  fields: [
    { name: "title", type: "text", required: true },
    { name: "content", type: "text" },
    { name: "published", type: "bool" },
    { name: "views", type: "number" },
  ],
});

Field Types

Type Description Example
text Plain text string "Hello"
email Email address "user@example.com"
number Numeric value 42 or 3.14
bool Boolean value true or false
date Date string "2024-01-01"
datetime Datetime with timezone "2024-01-01T00:00:00Z"
select Predefined options Use with options array
url URL string "https://example.com"
editor Rich text content HTML/Markdown content
json JSON object { "key": "value" }
relation Reference to another collection Use with collectionId

Auth Collections

const usersCollection = await client.settings.collections.create({
  name: "_users",
  type: "auth",
  fields: [
    { name: "email", type: "email", required: true },
    { name: "password", type: "text", required: true },
    { name: "name", type: "text" },
  ],
});

Auth collections automatically include system fields (id, created, updated).

Note: When creating collections, use the fields property. However, when reading collection data, the schema is returned as the schema property. Both keys are accepted for backwards compatibility.

Creating Records

Simple Create

const post = await client.collection("posts").create({
  title: "Hello World",
  content: "My first post",
  published: true,
  views: 0,
});

console.log(post.id); // Auto-generated ID
console.log(post.created); // Auto timestamp
console.log(post.updated); // Auto timestamp

Using Custom ID

const post = await client.collection("posts").create({
  id: "custom-post-id",
  title: "Custom ID Post",
  content: "Content here",
});

Reading Records

Get Single Record

const post = await client.collection("posts").getOne("record-id");
console.log(post.title);

List Records

const list = await client.collection("posts").getList(1, 20);
console.log(list.totalItems); // Total number of records
console.log(list.items); // Array of records on this page
console.log(list.totalPages); // Total pages

Filter Records

const filtered = await client.collection("posts").getList(1, 20, {
  filter: "published = true AND views > 10",
});

Sort Records

const sorted = await client.collection("posts").getList(1, 20, {
  sort: "-created", // Descending by creation date
});

// Multiple sort fields
const sorted2 = await client.collection("posts").getList(1, 20, {
  sort: "-published,created",
});

Select Specific Fields

const partial = await client.collection("posts").getList(1, 20, {
  fields: "id,title,published",
});

Updating Records

Update All Fields

const updated = await client.collection("posts").update("record-id", {
  title: "Updated Title",
  views: 100,
});

Partial Update (preserve unchanged fields)

const updated = await client.collection("posts").update("record-id", {
  title: "Just the title",
});

Deleting Records

const success = await client.collection("posts").delete("record-id");
console.log(success); // true

Query Filters

VSKI supports powerful SQL-like filters:

Comparison Operators

// Equals
client.filter("title = 'Hello'");

// Not equals
client.filter("status != 'deleted'");

// Greater than
client.filter("views > 100");

// Less than
client.filter("price < 50");

// Greater than or equal
client.filter("rating >= 4");

// Less than or equal
client.filter("age <= 18");

Logical Operators

// AND
client.filter("published = true AND featured = true");

// OR
client.filter("status = 'active' OR status = 'pending'");

// Parentheses for grouping
client.filter("(status = 'active' OR status = 'pending') AND published = true");

String Operators

// Contains (LIKE with wildcards)
client.filter("title ~ 'Hello'");

// Case-insensitive LIKE
client.filter("title LIKE 'hello'");

// Exact match with quotes
client.filter("title = 'Hello World'");

Note: The ~ operator performs a substring match (LIKE with wildcards). For prefix or suffix matching, use explicit wildcards: title ~ 'Hello%' is not needed as % wildcards are added automatically.

Null Checks

// Is null
client.filter("deleted = null");

// Is not null
client.filter("deleted != null");

Array Operations (for JSON fields)

// In array
client.filter("tags ~ ['javascript', 'typescript']");

// Contains array element
client.filter("tags ~ 'javascript'");

Pagination

// Get first page
const page1 = await client.collection("posts").getList(1, 20);

// Get next page
const page2 = await client.collection("posts").getList(2, 20);

// Check if there are more pages
if (page1.page < page1.totalPages) {
  // There are more pages
}

Expand Relations

When you have relation fields, you can expand them:

const post = await client.collection("posts").getOne("post-id", {
  expand: "author,category",
});

console.log(post.expand.author); // Full author record
console.log(post.expand.category); // Full category record

Collection Management

List Collections

const collections = await client.settings.collections.getList();
console.log(collections.items);

Get Collection Details

// Note: getOne method is not currently available
// Use getList to retrieve all collections and find by name
const collections = await client.settings.collections.getList();
const collection = collections.items.find((c) => c.name === "collection-name");
console.log(collection.name);
console.log(collection.schema);

Update Collection Schema

const updated = await client.settings.collections.update("collection-id", {
  fields: [
    { name: "title", type: "text", required: true },
    { name: "content", type: "text" },
    { name: "newField", type: "text" }, // Added new field
  ],
});

Delete Collection

await client.settings.collections.delete("collection-id");

Warning: This will delete all records in the collection.

Best Practices

  1. Use meaningful field names - Follow consistent naming conventions
  2. Set required fields - Use required: true for essential data
  3. Index frequently queried fields - Improve query performance
  4. Use appropriate types - Choose the most specific type for your data
  5. Validate on client side - Reduce unnecessary API calls
  6. Use pagination - Always use getList() with limits for large datasets

API Endpoints

Method Endpoint Description
GET /api/collections List collections
POST /api/collections Create collection
GET /api/collections/:name Get collection
PATCH /api/collections/:name Update collection
DELETE /api/collections/:name Delete collection
GET /api/collections/:name/records List records
POST /api/collections/:name/records Create record
GET /api/collections/:name/records/:recordId Get record
PATCH /api/collections/:name/records/:recordId Update record
PUT /api/collections/:name/records/:recordId Update record (full)
DELETE /api/collections/:name/records/:recordId Delete record
PATCH /api/collections/:name/records/bulk Bulk update records
DELETE /api/collections/:name/records/bulk Bulk delete records
GET /api/collections/:name/records/search Full-text search records
GET /api/collections/:name/records/views/:slug Get records from view