NyaruCollection
public struct NyaruCollection<T> : Sendable where T : Decodable, T : Encodable, T : Sendable
A typed, Sendable handle to one collection within a NyaruDB database.
NyaruCollection is a thin facade that encodes and decodes the generic
document type T and delegates all storage operations to a shared
CollectionCore actor. Handles are cheap value types — copy them freely.
Writing documents. Use insert, update, upsert, patch, and
delete:
try await collection.insert(user)
try await collection.patch(id: userId, changes: ["name": "New Name"])
Reading documents. Use get(id:) for point lookups, all() for
everything, stream() for bounded-memory iteration, and find() for
fluent queries with predicates, sorting, and pagination.
Maintenance. Call compact() opportunistically (e.g. on app
backgrounding) to reclaim space from tombstoned records.
-
The collection name as passed to
NyaruDB.collection(_:of:options:).Declaration
Swift
public let name: String
-
insert(_:Asynchronous) Inserts a new document into the collection.
The document must contain the configured
idField. If another document with the same id already exists, aduplicateIDerror is thrown.Throws
NyaruError.duplicateIDif the id already exists,NyaruError.encodingFailedif encoding fails.Declaration
Swift
public func insert(_ document: T) async throwsParameters
documentThe document to insert.
-
insert(contentsOf:Asynchronous) Inserts a batch of documents atomically.
All ids are validated before anything is written — if any id already exists in the collection or is duplicated within the batch, no documents are inserted and
duplicateIDis thrown.Throws
NyaruError.duplicateIDif any id conflicts.Declaration
Swift
public func insert(contentsOf documents: [T]) async throwsParameters
documentsAn array of documents to insert.
-
insertBatch(_:Asynchronous) Accumulates insert operations in memory and flushes them as a single batch when the body completes, producing one index merge pass instead of one per call.
Insertions inside the body are synchronous — no
awaitrequired:try await collection.insertBatch { batch in for chunk in incomingChunks { batch.insert(contentsOf: chunk) } }If the body throws, nothing is written to disk. This is a write buffer, not a transaction: update, delete, and patch are not buffered or rolled back — call them outside the batch.
Throws
Rethrows frombodyor from the final batch write.Declaration
Swift
public func insertBatch( _ body: (NyaruInsertBatch<T>) async throws -> Void ) async throwsParameters
bodyClosure receiving a
NyaruInsertBatchthat accumulates documents via its synchronousinsertmethods. -
update(_:Asynchronous) Replaces the document with the same id.
The full document is replaced (not merged). If no document with the given id exists,
documentNotFoundis thrown. To insert-or-replace, useupsertinstead.Throws
NyaruError.documentNotFoundif the id does not exist.Declaration
Swift
public func update(_ document: T) async throwsParameters
documentThe updated document.
-
upsert(_:Asynchronous) Replaces the document with the same id, or inserts it if absent.
Unlike
update, this never throwsdocumentNotFound— if no document exists for the id, the document is inserted.Declaration
Swift
public func upsert(_ document: T) async throwsParameters
documentThe document to upsert.
-
delete(id:Asynchronous) Deletes a document by its id.
The record is tombstoned in the shard file (space is reclaimed during compaction). The index entries are also removed.
Declaration
Swift
@discardableResult public func delete(id: FieldValueConvertible) async throws -> BoolParameters
idThe document id (any
FieldValueConvertibletype).Return Value
trueif a document was removed,falseif no document with that id existed. -
delete(ids:Asynchronous) Deletes multiple documents by id in a single batched pass: one storage hop per shard and one index sweep per field, instead of a full read/remove cycle per document.
Unknown ids are skipped (they do not count toward the result and do not throw).
Declaration
Swift
@discardableResult public func delete(ids: [FieldValueConvertible]) async throws -> IntParameters
idsThe document ids to delete.
Return Value
The number of documents actually deleted.
-
patch(id:Asynchronouschanges: ) Partially updates a document by applying top-level field changes without decoding the full document type.
This is useful when you want to change a few fields without fetching, decoding, modifying, re-encoding, and re-inserting the entire document. The merged document is validated against the type
Tbefore anything is written to disk.Restrictions:
- Only top-level fields can be patched (nested paths like
"address.city"are rejected). - The document id field cannot be changed through patch.
The merged result must still decode as
T, otherwise the patch is rejected and no data is written.
Throws
NyaruError.documentNotFoundif the id does not exist,NyaruError.decodingFailedif the merged document no longer decodes asT,NyaruError.unsupportedOperationfor nested paths or id changes.Declaration
Swift
public func patch(id: FieldValueConvertible, changes: [String : FieldValue]) async throwsParameters
idThe document id.
changesA dictionary of field names to new
FieldValues. - Only top-level fields can be patched (nested paths like
-
get(id:Asynchronous) Performs a point lookup by document id through the primary index.
Declaration
Swift
public func get(id: FieldValueConvertible) async throws -> T?Parameters
idThe document id.
Return Value
The decoded document, or
nilif no document with that id exists. -
count()AsynchronousReturns the total number of live documents in the collection.
Throws
NyaruError.databaseClosedif the database was closed.Declaration
Swift
public func count() async throws -> IntReturn Value
The live document count (excludes tombstoned records).
-
all()AsynchronousReturns every document in the collection.
For large collections this materialises the entire dataset in memory. Consider using
stream()for bounded-memory iteration.Throws
NyaruError.decodingFailedif any document fails to decode.Declaration
Swift
public func all() async throws -> [T]Return Value
An array of all decoded documents.
-
Returns a pull-based async sequence over all documents.
Each
next()call serves from an in-memory batch and only touches the collection actor when the batch is exhausted. Memory is bounded by one batch (batchSizeelements), making this suitable for iterating large collections without materialising everything at once.Declaration
Swift
public func stream(batchSize: Int = 64) -> NyaruDocumentStream<T>Parameters
batchSizeMaximum documents fetched per storage read (default 64).
Return Value
A
NyaruDocumentStream<T>(conforms toAsyncSequence). -
Returns a fluent query builder for this collection.
let results = try await collection.find() .where("age", isGreaterThan: 18) .sort(by: "name") .limit(10) .execute()Declaration
Swift
public func find() -> QueryBuilder<T>Return Value
An immutable
QueryBuilder<T>.
-
compact()AsynchronousRewrites every shard file to remove tombstoned records and rebuilds all indexes.
Call this opportunistically, such as when the app transitions to the background or after a significant number of deletions. There is no automatic background timer — compaction is always explicit.
Throws
I/O errors from shard or index operations.Declaration
Swift
public func compact() async throws -
needsCompaction()AsynchronousWhether any shard’s tombstone ratio exceeds the configured
DatabaseOptions.maxFragmentationthreshold.Use this to decide when to call
compact()— for example, on app backgrounding:if try await collection.needsCompaction() { try await collection.compact() }Throws
NyaruError.databaseClosedif the database was closed.Declaration
Swift
public func needsCompaction() async throws -> BoolReturn Value
trueif compaction would reclaim meaningful space. -
stats()AsynchronousReturns a snapshot of collection statistics.
The returned
CollectionStatsincludes the document count, shard count, total on-disk size, index entry counts, and the fragmentation ratio.Throws
NyaruError.databaseClosedif the database was closed.Declaration
Swift
public func stats() async throws -> CollectionStatsReturn Value
Current collection statistics.
View on GitHub