pub struct Docs { /* private fields */ }Expand description
Documents by id, with the key table their keys are interned against.
Implementations§
Source§impl Docs
impl Docs
Sourcepub fn with_capacity(n: usize, each: usize) -> Docs
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.
Sourcepub fn put(&mut self, id: &[u8], value: Value<'_>) -> Result<bool>
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.
Sourcepub fn put_bytes(&mut self, id: &[u8], doc: &[u8]) -> Result<bool>
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.
Sourcepub fn create_index(&mut self, path: &str) -> Result<()>
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.
Sourcepub fn create_ordered_index(&mut self, path: &str) -> Result<()>
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.
Sourcepub fn create_array_index(&mut self, path: &str) -> Result<()>
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.
Sourcepub fn create_text_index(&mut self, path: &str) -> Result<()>
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.
Sourcepub fn create_index_bytes(&mut self, path: &[u8], kind: IndexKind) -> Result<()>
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.
Sourcepub fn drop_index(&mut self, path: &str) -> bool
pub fn drop_index(&mut self, path: &str) -> bool
Stop indexing path, and say whether it was indexed.
Sourcepub fn drop_index_bytes(&mut self, path: &[u8]) -> bool
pub fn drop_index_bytes(&mut self, path: &[u8]) -> bool
Docs::drop_index for a path that is already bytes.
Sourcepub fn indexes(&self) -> &[PathIndex]
pub fn indexes(&self) -> &[PathIndex]
The indexes this collection keeps, in the order they were declared.
Sourcepub fn find(
&self,
path: &str,
key: &Key,
f: impl FnMut(&[u8], Doc<'_>),
) -> Result<usize>
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.
Sourcepub fn count(&self, path: &str, key: &Key) -> Result<usize>
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.
Sourcepub fn range(
&self,
path: &str,
lo: Bound<&Key>,
hi: Bound<&Key>,
f: impl FnMut(&[u8], Doc<'_>),
) -> Result<usize>
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.
Sourcepub fn range_rev(
&self,
path: &str,
lo: Bound<&Key>,
hi: Bound<&Key>,
f: impl FnMut(&[u8], Doc<'_>),
) -> Result<usize>
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.
Sourcepub fn count_range(
&self,
path: &str,
lo: Bound<&Key>,
hi: Bound<&Key>,
) -> Result<usize>
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.
Sourcepub fn bytes(&self, id: &[u8]) -> Option<&[u8]>
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.
Sourcepub fn remove(&mut self, id: &[u8]) -> bool
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.
Sourcepub fn iter(&self) -> impl Iterator<Item = (&[u8], Doc<'_>)>
pub fn iter(&self) -> impl Iterator<Item = (&[u8], Doc<'_>)>
Every document, in insertion order.
Sourcepub fn scan<F>(&self, cursor: Cursor, count: usize, f: F) -> Cursor
pub fn scan<F>(&self, cursor: Cursor, count: usize, f: F) -> Cursor
Walk part of the collection and say where to resume, the same contract
Elements::scan has.
Sourcepub fn clear(&mut self)
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.
Sourcepub fn memory_bytes(&self) -> usize
pub fn memory_bytes(&self) -> usize
What the collection costs, the key table and the indexes included.