Current section
Files
Jump to
Current section
Files
lib/aerospike/op/hll.ex
defmodule Aerospike.Op.HLL do
@moduledoc """
HyperLogLog operations for `Aerospike.operate/4`.
HyperLogLog bins require Aerospike server 4.9 or later. The server does not
support HyperLogLog bins nested inside lists or maps, so these operations do
not accept `ctx:`.
`init/4` and `add/5` default both bit counts to `-1`, which asks the server
to choose its defaults. When set explicitly, index bits are typically 4 to
16, min-hash bits 4 to 58, and their sum must not exceed 64.
Multi-HLL read operations accept `hlls` as a list of `{:bytes, blob}` HLL
values. Modify operations accept mnemonic `flags:` values for the server
write policy.
"""
alias Aerospike.PolicyInteger
alias Aerospike.Protocol.CDT
@typedoc """
Opaque HyperLogLog operation for `Aerospike.operate/4`.
"""
@opaque t :: Aerospike.Op.t()
@typedoc """
HyperLogLog write flags.
Accepts `:default`, `:create_only`, `:update_only`, `:no_fail`,
`:allow_fold`, or a list of those atoms. Compatibility callers may pass a
non-negative integer; use `{:raw, integer}` when deliberately sending an
unnamed server value.
"""
@type flags :: atom() | [atom()] | non_neg_integer() | {:raw, non_neg_integer()}
@typedoc """
Options accepted by HyperLogLog modify operations.
Supported key:
* `:flags` - HyperLogLog write flags. Defaults to `:default`.
"""
@type write_opts :: [flags: flags()]
@typedoc """
Options accepted by multi-HLL read helpers.
No option keys are currently encoded for these read operations; the argument
is accepted for API consistency.
"""
@type read_opts :: []
@init 0
@add 1
@set_union 2
@refresh_count 3
@fold 4
@count 50
@union 51
@union_count 52
@intersect_count 53
@similarity 54
@describe 55
@doc "Use default HyperLogLog write behavior."
@spec write_default() :: 0
def write_default, do: PolicyInteger.hll_write_flags(:default)
@doc "Only create the HyperLogLog bin when it does not already exist."
@spec write_create_only() :: 1
def write_create_only, do: PolicyInteger.hll_write_flags(:create_only)
@doc "Only update the HyperLogLog bin when it already exists."
@spec write_update_only() :: 2
def write_update_only, do: PolicyInteger.hll_write_flags(:update_only)
@doc "Do not fail the command when a HyperLogLog operation is denied by write flags."
@spec write_no_fail() :: 4
def write_no_fail, do: PolicyInteger.hll_write_flags(:no_fail)
@doc "Allow folding to less precise HyperLogLog settings when needed."
@spec write_allow_fold() :: 8
def write_allow_fold, do: PolicyInteger.hll_write_flags(:allow_fold)
@doc """
Creates a new HyperLogLog bin or resets an existing one.
"""
@spec init(String.t(), integer(), integer(), write_opts()) :: t()
def init(bin_name, index_bit_count \\ -1, min_hash_bit_count \\ -1, opts \\ [])
when is_binary(bin_name) and is_integer(index_bit_count) and
is_integer(min_hash_bit_count) and is_list(opts) do
CDT.hll_modify_op(bin_name, @init, [index_bit_count, min_hash_bit_count, flags(opts)])
end
@doc """
Adds elements to a HyperLogLog bin.
Elements may be strings or `{:bytes, binary}` values. If the bin is missing,
the server creates it using the supplied bit counts.
"""
@spec add(String.t(), list(), integer(), integer(), write_opts()) :: t()
def add(bin_name, elements, index_bit_count \\ -1, min_hash_bit_count \\ -1, opts \\ [])
when is_binary(bin_name) and is_list(elements) and is_integer(index_bit_count) and
is_integer(min_hash_bit_count) and is_list(opts) do
CDT.hll_modify_op(bin_name, @add, [elements, index_bit_count, min_hash_bit_count, flags(opts)])
end
@doc """
Merges every HyperLogLog value in `hlls` into the bin.
"""
@spec set_union(String.t(), list(), write_opts()) :: t()
def set_union(bin_name, hlls, opts \\ [])
when is_binary(bin_name) and is_list(hlls) and is_list(opts) do
CDT.hll_modify_op(bin_name, @set_union, [hlls, flags(opts)])
end
@doc """
Refreshes stale cached cardinality and returns the estimated count.
"""
@spec refresh_count(String.t()) :: t()
def refresh_count(bin_name) when is_binary(bin_name) do
CDT.hll_modify_op(bin_name, @refresh_count, [])
end
@doc """
Folds the HyperLogLog bin to a smaller index bit count.
"""
@spec fold(String.t(), integer()) :: t()
def fold(bin_name, index_bit_count) when is_binary(bin_name) and is_integer(index_bit_count) do
CDT.hll_modify_op(bin_name, @fold, [index_bit_count])
end
@doc """
Returns the estimated cardinality of the HyperLogLog bin.
"""
@spec get_count(String.t()) :: t()
def get_count(bin_name) when is_binary(bin_name) do
CDT.hll_read_op(bin_name, @count, [])
end
@doc """
Returns a HyperLogLog blob containing the union of the bin and `hlls`.
"""
@spec get_union(String.t(), list(), read_opts()) :: t()
def get_union(bin_name, hlls, opts \\ [])
when is_binary(bin_name) and is_list(hlls) and is_list(opts) do
CDT.hll_read_op(bin_name, @union, [hlls])
end
@doc """
Returns the estimated cardinality of the union of the bin and `hlls`.
"""
@spec get_union_count(String.t(), list(), read_opts()) :: t()
def get_union_count(bin_name, hlls, opts \\ [])
when is_binary(bin_name) and is_list(hlls) and is_list(opts) do
CDT.hll_read_op(bin_name, @union_count, [hlls])
end
@doc """
Returns the estimated cardinality of the intersection of the bin and `hlls`.
"""
@spec get_intersect_count(String.t(), list(), read_opts()) :: t()
def get_intersect_count(bin_name, hlls, opts \\ [])
when is_binary(bin_name) and is_list(hlls) and is_list(opts) do
CDT.hll_read_op(bin_name, @intersect_count, [hlls])
end
@doc """
Returns an estimated similarity score for the bin and `hlls`.
"""
@spec get_similarity(String.t(), list(), read_opts()) :: t()
def get_similarity(bin_name, hlls, opts \\ [])
when is_binary(bin_name) and is_list(hlls) and is_list(opts) do
CDT.hll_read_op(bin_name, @similarity, [hlls])
end
@doc """
Returns `[index_bit_count, min_hash_bit_count]` for the HyperLogLog bin.
"""
@spec describe(String.t()) :: t()
def describe(bin_name) when is_binary(bin_name) do
CDT.hll_read_op(bin_name, @describe, [])
end
defp flags(opts), do: opts |> Keyword.get(:flags, :default) |> PolicyInteger.hll_write_flags()
end