Persistence

CRUD Operations

Using generated entity services for create, read, update, delete, search, and count operations in Kinotic.

After defining your entities and running kinotic sync, you get fully typed repository classes for each entity. These repositories provide a complete set of data operations.

Setup

import { Kinotic } from '@kinotic-ai/core'
import { PersistencePlugin } from '@kinotic-ai/persistence'
import { PersonRepository } from './generated/PersonRepository'

Kinotic.use(PersistencePlugin)
await Kinotic.connect({ host: 'localhost', port: 58503 })

const service = new PersonRepository()

Create

Save a Single Entity

const person = await service.save({
    id: null,
    firstName: 'Jane',
    lastName: 'Doe',
    age: 28
})
// person.id is now set by the server

When using @AutoGeneratedId, pass null for the ID field. The server assigns a unique ID and returns it on the saved object.

Bulk Save

await service.bulkSave([
    { id: null, firstName: 'Alice', lastName: 'Smith', age: 30 },
    { id: null, firstName: 'Bob', lastName: 'Jones', age: 25 }
])

Bulk save is more efficient than calling save() in a loop because it batches the operations into a single request.

Read

Find by ID

const person = await service.findById('abc-123')

Find Multiple by IDs

const people = await service.findByIds(['abc-123', 'def-456'])

Find All with Pagination

const page = await service.findAll({ page: 0, size: 20 })
console.log(page.content)       // array of Person
console.log(page.totalElements)  // total count across all pages

The page parameter is zero-indexed. The returned page object includes the content array, total element count, and pagination metadata.

Perform full-text search across all fields marked with @Text.

const results = await service.search('Jane', { page: 0, size: 10 })

The search string is matched against all text-indexed fields on the entity.

Update

person.age = 29
const updated = await service.update(person)

The update() method only changes fields present in the object. Fields not included in the update payload are left unchanged.

Delete

Delete by ID

await service.deleteById('abc-123')

Delete by Query

await service.deleteByQuery('age < 18')

Count

Count All

const total = await service.count()

Count by Query

const adults = await service.countByQuery('age >= 18')

Sync Index

After performing writes, changes may not be immediately available for search. Call syncIndex() to ensure recent writes are queryable.

await service.syncIndex()
// Recent writes are now immediately available for search

This is useful in scripts or tests where you need to query data right after writing it. In production, the platform refreshes automatically at a short interval.

Copyright © 2026