Expand description
Collections and types used when interacting with storage.
§Benchmarks of comparison with std::collections
:
To help you understand how cost-effective near collections are in terms of gas usage compared to native ones, take a look at this investigation: Near benchmarking github.
The results of the investigation can be found here: Results.
If your collection has up to 100 entries, it’s acceptable to use the native collection, as it might be simpler
since you don’t have to manage prefixes as we do with near collections.
However, if your collection has 1,000 or more entries, it’s better to use a near collection. The investigation
mentioned above shows that running the contains method on a native std::collections::HashSet<i32>
consumes 41% more gas
compared to a near crate::store::IterableSet<i32>
.
§FAQ: collections of this module
only persist on Drop
and flush
Unlike containers in near_sdk::collections
module, most containers in current module
will cache all changes
and loads and only update values that are changed in storage after it’s dropped through it’s Drop
implementation.
These changes can be updated in storage before the container variable is dropped by using
the container’s flush
method, e.g. IterableMap::flush
(IterableMap::drop
uses it in implementation too).
use near_sdk::store::IterableMap;
#[near(contract_state)]
#[derive(Debug)]
pub struct Contract {
greeting_map: IterableMap<String, String>,
}
#[near]
impl Contract {
pub fn mutating_method(&mut self, argument: String) {
self.greeting_map.insert("greeting".into(), argument);
near_sdk::env::log_str(&format!("State of contract mutated: {:#?}", self));
}
}
// expanded #[near] macro call on a contract method definition:
// ...
let mut contract: Contract = ::near_sdk::env::state_read().unwrap_or_default();
// call of the original `mutating_method` as defined in source code prior to expansion
Contract::mutating_method(&mut contract, argument);
::near_sdk::env::state_write(&contract);
// Drop on `contract` is called! `IterableMap` is only `flush`-ed here <====
// ...
§General description
These collections are more scalable versions of std::collections
when used as contract
state because it allows values to be lazily loaded and stored based on what is actually
interacted with.
Fundamentally, a contract’s storage is a key/value store where both keys and values are just
Vec<u8>
. If you want to store some structured data, for example, Vec<Account>
, one way
to achieve that would be to serialize the Vec to bytes and store that. This has a drawback in
that accessing or modifying a single element would require reading the whole Vec
from the
storage.
That’s where store
module helps. Its collections are backed by a key value store.
For example, a store::Vector is stored as several key-value pairs, where indices are the keys.
So, accessing a single element would only load this specific element.
It’s also a bad practice to have a native collection properties as a top level properties of your contract. The contract will load all the properties before the contract method invocation. That means that all your native collections will be fully loaded into memory even if they are not used in the method you invoke.
It can be expensive to load all values into memory, and because of this, serde
Serialize
and Deserialize
traits are
intentionally not implemented. If you want to return all values from a storage collection from
a function, consider using pagination with the collection iterators.
All of the collections implement BorshSerialize
and
BorshDeserialize
to be able to store the metadata of the
collections to be able to access all values. Because only metadata is serialized, these
structures should not be used as a borsh return value from a function.
§Calls to host functions, used in implementation:
near_sdk::env::storage_write
near_sdk::env::storage_read
near_sdk::env::storage_remove
near_sdk::env::storage_has_key
§Module’s glossary:
The collections are as follows:
Sequences:
Maps:
-
LookupMap
: Wrapper around key-value storage interactions, similar toUnorderedMap
/std::collections::HashMap
except that keys are not persisted and cannot be iterated over. -
UnorderedMap
: DEPRECATED storage version ofstd::collections::HashMap
. No ordering guarantees. -
IterableMap
: a replacement with better iteration performance forUnorderedMap
, which is being deprecated. -
TreeMap
(unstable
): Storage version ofstd::collections::BTreeMap
. Ordered by key, which comes at the cost of more expensive lookups and iteration.
Sets:
-
LookupSet
: Non-iterable storage version ofstd::collections::HashSet
. -
UnorderedSet
: DEPRECATED analogous tostd::collections::HashSet
, and is an iterable version ofLookupSet
and persisted to storage. -
IterableSet
: a replacement with better iteration performance forUnorderedSet
, which is being deprecated.
Basic Types:
-
Lazy<T>
: Lazily loaded type that can be used in place of a typeT
. Will only be loaded when interacted with and will persist onDrop
. -
LazyOption<T>
: Lazily loaded, optional type that can be used in place of a typeOption<T>
. Will only be loaded when interacted with and will persist onDrop
.
- More information about collections can be found in NEAR documentation
- Benchmarking results of the NEAR-SDK store collections vs native collections can be found in github
Re-exports§
pub use vec::Vector;
pub use self::lookup_map::LookupMap;
pub use self::iterable_map::IterableMap;
pub use self::iterable_set::IterableSet;
pub use self::unordered_map::UnorderedMap;
Deprecated pub use self::unordered_set::UnorderedSet;
Deprecated pub use self::tree_map::TreeMap;
Modules§
- iterable_
map - iterable_
set - key
- Storage key hash function types and trait to override map hash functions.
- lookup_
map - tree_
map - unordered_
map - unordered_
set - vec
- A growable array type with values persisted to storage and lazily loaded.
Structs§
- Lazy
- An persistent lazily loaded value, that stores a value in the storage.
- Lazy
Option - An persistent lazily loaded option, that stores a
value
in the storage whenSome(value)
is set, and not whenNone
is set.LazyOption
alsoDeref
s intoOption
so we get all its APIs for free. - Lookup
Set - A non-iterable implementation of a set that stores its content directly on the storage trie.