Skip to main content

Docs

Struct Docs 

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

Documents by id, with the key table their keys are interned against.

Implementations§

Source§

impl Docs

Source

pub fn new() -> Docs

An empty collection that has not allocated anything yet.

Source

pub fn with_capacity(n: usize, each: usize) -> Docs

An empty collection with room for n documents of about each bytes.

The ids and the documents share one blob, so the size asked for is the two of them together. Getting it wrong costs a growth, not a rewrite.

Source

pub fn put(&mut self, id: &[u8], value: Value<'_>) -> Result<bool>

Store value under id, and say whether the id is new.

The value is re-encoded with this collection’s interned keys on the way in. It may not already be interned: a document whose keys are ids belongs to whichever collection handed those ids out, and moving it to another one without the names is how a collection ends up reading the wrong field.

Source

pub fn put_bytes(&mut self, id: &[u8], doc: &[u8]) -> Result<bool>

Store the document doc encodes under id, and say whether the id is new.

The bytes are checked far enough to be readable and no further, the same as Value::new. A caller holding bytes it did not write should run Value::validate first.

Source

pub fn create_index(&mut self, path: &str) -> Result<()>

Start indexing path for equality, and file every document already here under it.

Declaring the same path twice is not an error and does not rebuild anything, because a caller that opens a collection and declares its indexes on the way in should be able to do that every time it opens it. An ordered index that is already there stays ordered, since it answers equality as well.

The backfill is a path lookup per document, so it costs the collection once. There is no background indexer and no window in which the index is declared and not yet true, which is Y3.

Source

pub fn create_ordered_index(&mut self, path: &str) -> Result<()>

Start indexing path for equality and for ranges.

An ordered index is an equality index with a counted B+ tree over the rows of its key table, which is the same tree a sorted set ranks with. It costs about three bytes per distinct value on top of the equality index and a logarithmic search per new value, and it is what Docs::range needs.

A path that is already indexed for equality is upgraded and rebuilt. The alternative is answering Ok and then having every range on it come back empty, which is a query that lies.

Source

pub fn create_array_index(&mut self, path: &str) -> Result<()>

Start indexing every element of the array at path.

A document with ["red", "blue"] there is filed under both, so a search for either finds it. A scalar at the path is an array of one, so a collection where some documents have a list of tags and some have a single tag works without the caller having to normalise it first.

The lookup is Docs::find with the element as the key, unchanged. An array index costs what the document has at the path, so a document with ten elements costs ten postings and a document with none costs nothing.

Source

pub fn create_text_index(&mut self, path: &str) -> Result<()>

Start indexing every word of the string at path.

A document with "A red bicycle" there is filed under a, red and bicycle, and the lookup is Docs::find with Key::word as the key. Case is folded on both sides, so a search does not have to know how the document was written.

This is a word index and not a search engine. There is no ranking, no stemming and no phrase matching, and a path that holds something other than a string files nothing. What it answers is which documents contain a word, which is a filter, and the ranking that belongs on top of it is 10.

Source

pub fn create_index_bytes(&mut self, path: &[u8], kind: IndexKind) -> Result<()>

Docs::create_index and Docs::create_ordered_index for a path that is already bytes.

Source

pub fn drop_index(&mut self, path: &str) -> bool

Stop indexing path, and say whether it was indexed.

Source

pub fn drop_index_bytes(&mut self, path: &[u8]) -> bool

Docs::drop_index for a path that is already bytes.

Source

pub fn indexes(&self) -> &[PathIndex]

The indexes this collection keeps, in the order they were declared.

Source

pub fn index(&self, path: &str) -> Option<&PathIndex>

The index on path, if there is one.

Source

pub fn find( &self, path: &str, key: &Key, f: impl FnMut(&[u8], Doc<'_>), ) -> Result<usize>

Hand every document whose value at path is key to f, and say how many there were.

One probe of the index and one probe of the primary table per document, which is the cost model 09 section 5 states rather than hides. A path with no index on it is an error and not a scan: a query that silently turns into a walk of the collection is the thing this API exists not to do.

Source

pub fn count(&self, path: &str, key: &Key) -> Result<usize>

How many documents have key at path, without reading any of them.

The number a caller sorts its filters by before it intersects them, and it is a probe rather than a walk.

Source

pub fn range( &self, path: &str, lo: Bound<&Key>, hi: Bound<&Key>, f: impl FnMut(&[u8], Doc<'_>), ) -> Result<usize>

Hand every document whose value at path falls between lo and hi to f, smallest first, and say how many there were.

One search of the tree and then a walk, so the cost is the size of the answer and not the size of the collection. The bounds are the ordinary Bound, so a half open range, a range open at one end and a range open at both are all the same call.

The path has to carry an ordered index. An equality index has no order to walk, and answering nothing would be a query that lies rather than a query that says no.

Source

pub fn range_rev( &self, path: &str, lo: Bound<&Key>, hi: Bound<&Key>, f: impl FnMut(&[u8], Doc<'_>), ) -> Result<usize>

Docs::range backwards, largest value first.

Source

pub fn count_range( &self, path: &str, lo: Bound<&Key>, hi: Bound<&Key>, ) -> Result<usize>

How many documents fall between lo and hi at path, without reading any of them.

This reads the distinct values in the range rather than the documents, so a range covering a million documents under a hundred values costs a hundred.

Source

pub fn get(&self, id: &[u8]) -> Option<Doc<'_>>

The document stored under id.

Source

pub fn bytes(&self, id: &[u8]) -> Option<&[u8]>

The stored bytes of the document under id, as they sit in the blob.

For a caller that is going to write them somewhere else rather than read them, which is DUMP, replication and the record plane.

Source

pub fn contains(&self, id: &[u8]) -> bool

Whether there is a document under id.

Source

pub fn remove(&mut self, id: &[u8]) -> bool

Take the document under id out, and say whether there was one.

Every index the document was filed in loses it first, so a removal costs a path lookup per index on the way out.

The key table is left alone. A name it interned stays interned even if this was the last document using it, which is Keys’s rule and the reason an id is a row index.

Source

pub fn len(&self) -> usize

How many documents there are.

Source

pub fn is_empty(&self) -> bool

Whether the collection holds nothing.

Source

pub fn keys(&self) -> &Keys

The names this collection has interned.

Source

pub fn iter(&self) -> impl Iterator<Item = (&[u8], Doc<'_>)>

Every document, in insertion order.

Source

pub fn scan<F>(&self, cursor: Cursor, count: usize, f: F) -> Cursor
where F: FnMut(&[u8], Doc<'_>),

Walk part of the collection and say where to resume, the same contract Elements::scan has.

Source

pub fn clear(&mut self)

Throw every document away and keep the key table and the allocations.

The indexes stay declared and go empty, for the same reason the key table stays: a caller that empties a collection is refilling it, and an index that quietly disappeared when the last document did would turn the next query into an error.

The key table stays because a collection that is emptied is usually a collection that is about to be refilled with the same shape of document, and relearning twenty names is work with nothing to show for it.

Source

pub fn memory_bytes(&self) -> usize

What the collection costs, the key table and the indexes included.

Trait Implementations§

Source§

impl Debug for Docs

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for Docs

Source§

fn default() -> Docs

Not derived, because the primary table has to be the kind that keeps a document behind its id and an empty Elements is not.

Auto Trait Implementations§

§

impl Freeze for Docs

§

impl RefUnwindSafe for Docs

§

impl Send for Docs

§

impl Sync for Docs

§

impl Unpin for Docs

§

impl UnsafeUnpin for Docs

§

impl UnwindSafe for Docs

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> 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, 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.