pub struct Collection<'tx, T: Document> { /* private fields */ }Expand description
Typed handle to a collection.
Construct via crate::WriteTxn::collection (lazy-create) or
crate::ReadTxn::collection (read-only; errors if absent).
All methods take &self because the underlying state lives
behind mutexes on the parent transaction; the handle itself is
stateless beyond the descriptor it caches.
Implementations§
Source§impl<'tx, T: Document> Collection<'tx, T>
impl<'tx, T: Document> Collection<'tx, T>
Sourcepub fn descriptor(&self) -> &CollectionDescriptor
pub fn descriptor(&self) -> &CollectionDescriptor
Cached descriptor (collection_id, primary_root,
type_version, next_id at handle-open time).
Sourcepub fn insert(&self, doc: T) -> Result<Id>
pub fn insert(&self, doc: T) -> Result<Id>
Insert doc. Returns the freshly-allocated Id.
§Errors
Error::ReadOnlyif the handle is read-only.- Pager / catalog / codec errors propagated.
Sourcepub fn get(&self, id: Id) -> Result<Option<T>>
pub fn get(&self, id: Id) -> Result<Option<T>>
Fetch the document at id.
On the write side this consults the pager (sees pending writes in the current txn). On the read side it consults the snapshot’s frozen view.
§Lazy migration (M10 #84)
If the on-disk record was written by an older
Document::VERSION than the current T::VERSION, the codec
walks the stored bytes through the schema registered for
that version (see T::historical_schemas()) and dispatches
the resulting structured Dynamic through T::migrate.
The migrated bytes are NOT written back to disk. The
next Collection::get re-reads the same v(n) bytes and
re-runs migration. Only a subsequent
Collection::update /
Collection::upsert writes the document
back, at which point the on-disk header records
T::VERSION.
This contract is what allows mixed-version reads to scale:
a 10⁹-doc collection does not need to be batch-rewritten on
schema upgrade. Power-of-ten Rule 7: every “migration ran”
path returns the migrated T; no implicit write-back.
§Errors
Pager / B-tree / codec errors propagated. In particular:
Error::SchemaNotRegisteredif the stored record carries atype_versionfor whichT::historical_schemas()has no entry.Error::SchemaMigrationNotImplementedif the registeredT::migratereturns the default error.
Sourcepub fn update<F>(&self, id: Id, f: F) -> Result<()>
pub fn update<F>(&self, id: Id, f: F) -> Result<()>
Apply f to the document at id, writing the mutated value
back.
§Errors
Error::ReadOnlyon a read-side handle.Error::DocumentNotFoundifidis absent.- Pager / catalog / codec errors propagated.
Sourcepub fn delete(&self, id: Id) -> Result<bool>
pub fn delete(&self, id: Id) -> Result<bool>
Delete the document at id. Returns true if it existed.
§Errors
Error::ReadOnlyon a read-side handle.- Pager / catalog errors propagated.
Sourcepub fn upsert(&self, id: Id, doc: T) -> Result<()>
pub fn upsert(&self, id: Id, doc: T) -> Result<()>
Insert-or-replace doc at id.
§Errors
Error::ReadOnlyon a read-side handle.- Pager / catalog / codec errors propagated.
Sourcepub fn find_unique(
&self,
index_name: &str,
key: impl Into<Dynamic>,
) -> Result<Option<T>>
pub fn find_unique( &self, index_name: &str, key: impl Into<Dynamic>, ) -> Result<Option<T>>
Look up the single document whose index_name key matches
key under a Unique index.
Errors with Error::IndexNotUnique if index_name resolves
to a non-unique index — find_unique is only defined on
Unique indexes. For Standard / Each / Composite use
Self::lookup (which returns an iterator).
Snapshot-aware: on a write-side handle the lookup sees the current txn’s pending writes; on a read-side handle it sees the snapshot’s frozen view.
§Errors
Error::IndexNotFoundifindex_nameis unknown / dropped.Error::IndexNotUniqueif the index is notUnique.- Pager / B-tree / codec errors propagated.
Sourcepub fn lookup(
&self,
index_name: &str,
key: impl Into<Dynamic>,
) -> Result<Box<dyn Iterator<Item = Result<T>> + Send + 'static>>where
T: Send + 'static,
pub fn lookup(
&self,
index_name: &str,
key: impl Into<Dynamic>,
) -> Result<Box<dyn Iterator<Item = Result<T>> + Send + 'static>>where
T: Send + 'static,
Yield every document whose index_name key matches key.
Works on Standard / Unique / Each indexes. Returns
Err(Error::IndexKindMismatch)-style guidance for
Composite (use Self::index_range for tuple-shaped
keys).
The same document is yielded at most once even if it owns
multiple matching entries — Each indexes can encode the
same id under multiple element keys; we de-dup on emit.
§Errors
Error::IndexNotFoundifindex_nameis unknown / dropped.- Pager / B-tree / codec errors propagated.
Sourcepub fn index_range(
&self,
index_name: &str,
range: impl RangeBounds<Vec<u8>>,
) -> Result<Box<dyn Iterator<Item = Result<(Vec<u8>, T)>> + Send + 'static>>where
T: Send + 'static,
pub fn index_range(
&self,
index_name: &str,
range: impl RangeBounds<Vec<u8>>,
) -> Result<Box<dyn Iterator<Item = Result<(Vec<u8>, T)>> + Send + 'static>>where
T: Send + 'static,
Yield (encoded_key, doc) pairs whose encoded key bytes
fall within range. The range bounds are bytes (the
caller is responsible for producing them through
encode_field / encode_index_key); this keeps the
signature general for Composite “starts-with” scans.
For non-Unique kinds (Standard / Each / Composite) the
bounds are widened internally so a user-facing
Included(x)..=Included(x) range matches every entry whose
user-key equals x even though the underlying B-tree key
carries an id_be8 suffix (see docs/format.md § Index key
encoding § Range-bound widening (non-Unique kinds)).
§Errors
Error::IndexNotFoundifindex_nameis unknown / dropped.- Pager / B-tree / codec errors propagated.
Sourcepub fn count_all(&self) -> Result<u64>
pub fn count_all(&self) -> Result<u64>
Count every entry in the primary tree WITHOUT decoding the
documents. Used by the M8 crate::Query::count no-decode
fast path; the iterator visits leaf pages and counts entries
rather than running each through postcard.
Power-of-ten Rule 2: bounded by the B+tree’s MAX_RANGE_NODES
budget (inherited from BTree::range).
§Errors
Pager / B-tree errors propagated.
Sourcepub fn count_index_range(
&self,
index_name: &str,
range: impl RangeBounds<Vec<u8>>,
) -> Result<u64>
pub fn count_index_range( &self, index_name: &str, range: impl RangeBounds<Vec<u8>>, ) -> Result<u64>
Count every entry whose encoded key falls inside range on
the named index’s B-tree, WITHOUT decoding any document. M8
fast path for crate::Query::count when the source is an
index_range.
Returns the number of index B-tree entries — for an Each
index that may exceed the document count (one doc emits
multiple entries); for other kinds it equals the matching
doc count.
§Errors
Error::IndexNotFoundifindex_nameis unknown / dropped.- Pager / B-tree errors propagated.
Sourcepub fn count_distinct_ids_in_range(
&self,
index_name: &str,
range: impl RangeBounds<Vec<u8>>,
) -> Result<u64>
pub fn count_distinct_ids_in_range( &self, index_name: &str, range: impl RangeBounds<Vec<u8>>, ) -> Result<u64>
Count distinct document Ids whose entries fall inside
range on the named index’s B-tree, WITHOUT decoding any
document. For Each indexes this is the correct shape of
the “how many docs match” question — count_index_range
returns the entry count, which overshoots when a single doc
contributes multiple entries.
Implementation walks the index B-tree, parses the trailing
8-byte big-endian Id suffix from each non-unique key, and
tracks the unique set in a bounded std::collections::HashSet
capped at MAX_DISTINCT_IDS. Exceeding the cap surfaces
Error::DistinctCountExceeded — the caller should narrow
the range.
§Per-kind semantics
Standard,Composite: equivalent tocount_index_range(one entry per doc by construction; the trailing-id-suffix walk still produces the same total).Unique: keys carry NO id suffix — the entry value is the raw 8-byteId; the walk reads the value instead.Each: the dedup is meaningful — one doc may contribute N entries under N distinct element keys.
§Errors
Error::IndexNotFoundifindex_nameis unknown / dropped.Error::DistinctCountExceededif the distinct set exceedsMAX_DISTINCT_IDS.Error::Corruptionif an entry’s id suffix / value is not parseable as anobj_core::Id.- Pager / B-tree errors propagated.
Sourcepub fn all(&self) -> Result<Vec<(Id, T)>>
pub fn all(&self) -> Result<Vec<(Id, T)>>
Materialise every (Id, T) pair in the collection.
Implementation note: M6 returns an owned Vec rather than a
streaming iterator because the B+tree range API borrows the
pager, and threading that borrow through the mutex guards
in the iterator chain is awkward. M7+ may convert to a
streaming shape once the index API is in place.
§Errors
Pager / B-tree / codec errors propagated.