@spec primary_key(t(), index_name(), non_primary_key()) :: {:ok, primary_key()} | :error
Returns the primary key of a value under the given non-primary key.
Collection allowing access via dynamically created indices.
The API is similar to Map
. See create_index/3
for more details
about indices.
iex> users = [%{name: "Bob", age: 20}, %{name: "Eve", age: 27}, %{name: "John", age: 45}]
iex> idx = Idx.new(users, & &1.name)
iex> Idx.get(idx, "Bob")
%{name: "Bob", age: 20}
iex> idx |> Enum.to_list() |> Enum.sort()
users
Index function. Returns a key based on the value to be indexed. Must be pure (always return the same key for the same value).
Creates a new non-primary index on the Idx
instance.
Updates the value under the key by calling fun
. No indices can change after the update.
Callback implementation for Access.fetch/2
.
Callback implementation for Access.get_and_update/3
.
Allows accessing a value by a non-primary key in the idx.
Creates a new Idx instance.
Returns the primary key of a value under the given non-primary key.
Converts idx
to a map, where keys are the primary keys of the idx
.
@type full_key() :: primary_key() | non_primary_key()
Index function. Returns a key based on the value to be indexed. Must be pure (always return the same key for the same value).
@type index_name() :: atom()
@type key() :: any()
@opaque non_primary_key()
@type primary_key() :: key()
@type value() :: any()
@spec create_index(t(), index_name(), index(), [{:lazy?, boolean()}]) :: t()
Creates a new non-primary index on the Idx
instance.
iex> users = [%{name: "Bob", age: 20}, %{name: "Eve", age: 27}, %{name: "John", age: 45}]
iex> idx = Idx.new(users, & &1.name)
iex> idx = Idx.create_index(idx, :initial, &String.first(&1.name))
iex> Idx.get(idx, Idx.key(:initial, "J"))
%{name: "John", age: 45}
If lazy
option is set to true, the index keys won't be precomputed and stored,
instead it will always be calculated on demand. This will slow down access, but
speed up insertion and operations relying on other indices.
@spec drop_index(t(), index_name()) :: t()
Updates the value under the key by calling fun
. No indices can change after the update.
Thanks to the guarantee that the indices (including the primary index)
won't change, this function is faster than update!/3
. However, if the
indices change, it will leave the idx
in an invalid state and lead
to undefined behaviour.
Callback implementation for Access.fetch/2
.
@spec get_and_update(t(), full_key(), (value() | nil -> {get, update} | :pop)) :: {get, t()} when get: any(), update: value()
Callback implementation for Access.get_and_update/3
.
@spec key(index_name(), non_primary_key()) :: full_key()
Allows accessing a value by a non-primary key in the idx.
See create_index/3
for details.
@spec new(Enumerable.t(), index()) :: t()
Creates a new Idx instance.
@spec primary_key(t(), index_name(), non_primary_key()) :: {:ok, primary_key()} | :error
Returns the primary key of a value under the given non-primary key.
@spec primary_key!(t(), index_name(), non_primary_key()) :: primary_key()
@spec size(t()) :: non_neg_integer()
Converts idx
to a map, where keys are the primary keys of the idx
.