Skip to main content

Db

Struct Db 

Source
pub struct Db { /* private fields */ }
Expand description

An open database.

Cheap to clone, and every clone is the same database. A handle taken out of it stays valid for as long as any clone lives.

This build runs in inline mode (15 section 7): the calling thread is the shard, which is what makes a point read a function call rather than a message. That is also why a handle does not cross threads yet. The owned and served modes put the same API on top of yo-shard’s runtime, and they arrive with it.

Implementations§

Source§

impl Db

Source

pub fn map<K: Decode, V: Decode>(&self, name: &str) -> Result<Map<K, V>>

Open a map, creating it if this is the first time.

The type is the collection’s shape (15 section 3), so opening the same name a second time with a different type is an error and not a surprise later: the shapes are compared, and a mismatch says which field moved and whether the change is additive or breaking.

§Errors

Code::ShapeMismatch when the name is already a collection of another shape.

Source

pub fn docs<T: Document>(&self, name: &str) -> Result<Docs<T>>

Open a collection of documents, creating it if this is the first time.

T is the collection’s shape, exactly as it is for Db::map, and it also carries the indexes: every field the type marked with #[yo(index)] or one of its friends is declared here, so a collection cannot be opened without the indexes its queries need.

use yo::Yo;

#[derive(Yo)]
struct Order {
    #[yo(id)]
    id: u64,
    #[yo(index)]
    status: String,
}

let db = yo::open(yo::MEMORY)?;
let orders = db.docs::<Order>("orders")?;

orders.put(&Order { id: 7, status: "open".to_owned() })?;
assert_eq!(orders.find(Order::STATUS, "open")?.len(), 1);
§Errors

Code::ShapeMismatch when the name is already a collection of another shape, and Code::Invalid for a declared index whose path is not one.

Source

pub fn graph(&self, name: &str) -> Result<Graph>

Open a graph, creating it if this is the first time.

The name has one shape like every other collection, and it is the same shape for every graph, because a graph’s types are not fixed when it is opened. A node type or an edge type registers itself under its label the first time it is used, and the shape it registered is checked on every later use, so the check is per label rather than one tuple named up front. That way adding a node type to a program is not a schema change for the types already in the graph.

use yo::{Edge, Node, Yo};

#[derive(Yo)]
struct Person { #[yo(id)] id: u64, name: String }

#[derive(Yo)]
struct Follows { since: i64 }

impl Node for Person { const LABEL: &'static str = "Person"; }
impl Edge for Follows {
    type From = Person;
    type To = Person;
    const LABEL: &'static str = "FOLLOWS";
}

let db = yo::open(yo::MEMORY)?;
let g = db.graph("social")?;

let ada = g.add(&Person { id: 1, name: "ada".to_owned() })?;
let grace = g.add(&Person { id: 2, name: "grace".to_owned() })?;
g.link(ada, grace, &Follows { since: 2026 })?;

assert_eq!(g.out::<Follows>(ada)?, vec![grace]);
§Errors

Code::ShapeMismatch when the name is already a collection of another shape, which includes a name that is already a map or a document collection.

Source

pub fn vectors(&self, name: &str, dim: usize) -> Result<Vectors>

Open a collection of vectors, creating it if this is the first time.

Nearness is euclidean distance. Db::vectors_with is the same call with the metric spelled out, and cosine is the other one worth having.

The dimension is part of the collection’s shape exactly as a map’s value type is, so a collection opened at 768 dimensions cannot later be opened at 1536 and quietly read the old vectors as half of a new one.

let db = yo::open(yo::MEMORY)?;
let v = db.vectors("passages", 3)?;

v.put("a", &[1.0, 0.0, 0.0])?;
v.put("b", &[0.0, 1.0, 0.0])?;

assert_eq!(v.search(&[0.9, 0.1, 0.0], 1)?[0].key, b"a".to_vec());
§Errors

Code::ShapeMismatch when the name is already a collection of another shape, which includes the same name at another dimension or metric, and Code::Invalid for a dimension no collection can hold.

Source

pub fn vectors_with( &self, name: &str, dim: usize, metric: Metric, ) -> Result<Vectors>

The same, saying what nearness means.

Metric::Cosine stores the unit vector and reports one minus the cosine similarity, which is what a collection of text embeddings wants. See the vector module for what each metric does and why two of the four are refused.

§Errors

As Db::vectors, and Code::Unsupported for a metric this build does not measure.

Source

pub fn strings(&self) -> Strings

The Redis string keyspace.

The same store a client reaches over RESP, reached without the socket, the parser or the reply (Y23). Not a named collection, because in Redis a string is not one: it is the keyspace itself.

let db = yo::open(yo::MEMORY)?;
assert_eq!(db.strings().incr("hits")?, 1);
Source

pub fn counter(&self, key: impl Into<Vec<u8>>) -> Counter

A counter at one key, which is 15 section 2’s db.counter("hits").

Sugar over Db::strings and worth having: a counter is the commonest thing a string key is, and a handle that holds the key means the key is spelled once rather than at every call site.

let db = yo::open(yo::MEMORY)?;
let hits = db.counter("hits");

hits.incr()?;
hits.add(9)?;
assert_eq!(hits.get()?, 10);
Source

pub fn sets(&self) -> Sets

Every Redis set command, with the key as the first argument.

The same store SADD off a socket reaches. Like Db::strings this is not a named collection, because in Redis a set is not one: it is a key in the keyspace that happens to hold a set.

let db = yo::open(yo::MEMORY)?;
db.sets().add_many("online", &["alice", "bob"])?;
assert_eq!(db.sets().len_of("online")?, 2);
Source

pub fn set(&self, key: impl Into<Vec<u8>>) -> Set

A set at one key, which is the same sugar Db::counter is.

let db = yo::open(yo::MEMORY)?;
let online = db.set("online");

online.add("alice")?;
assert!(online.contains("alice")?);
Source

pub fn keys(&self) -> Keys

Every command that works on a key whatever the key holds.

DEL, EXISTS and TYPE, and the whole expiry family. These are the ones that belong to the keyspace rather than to a type, which is why they are not on Db::strings or Db::sets: a deadline sits in the key’s record and does not care what the record points at.

use std::time::Duration;

let db = yo::open(yo::MEMORY)?;
db.set("online").add("alice")?;
db.keys().expire_in("online", Duration::from_secs(60))?;
Source

pub fn collections(&self) -> Result<Vec<String>>

The names of the typed collections in this database, in the order they were first opened.

§Errors

Code::Invalid if called from inside a callback that is already holding this database.

Source

pub fn shape(&self, name: &str) -> Result<Option<Tag>>

The shape of a collection, if it exists.

§Errors

Code::Invalid if called from inside a callback that is already holding this database.

Source

pub fn memory_bytes(&self) -> Result<usize>

What this database is holding, index and arena together, across the keyspace and every typed collection.

§Errors

Code::Invalid if called from inside a callback that is already holding this database.

Source

pub fn reads_the_clock(&self) -> bool

Whether this database reads the clock on the data path.

False until something is given a deadline, because until then the clock’s answer cannot change any reply. 04 section 5 is the reason this is worth a method: a clock read is tens of nanoseconds against a budget of a hundred and fifty.

Source

pub fn is(&self, other: &Db) -> bool

Whether two databases are the same one.

Trait Implementations§

Source§

impl Clone for Db

Source§

fn clone(&self) -> Db

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Db

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Db

§

impl !Send for Db

§

impl !Sync for Db

§

impl !UnwindSafe for Db

§

impl Freeze for Db

§

impl Unpin for Db

§

impl UnsafeUnpin for Db

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.