pub trait MergeOperator {
// Required method
fn merge(
&self,
key: &Bytes,
existing_value: Option<Bytes>,
value: Bytes,
) -> Result<Bytes, MergeOperatorError>;
// Provided method
fn merge_batch(
&self,
key: &Bytes,
existing_value: Option<Bytes>,
operands: &[Bytes],
) -> Result<Bytes, MergeOperatorError> { ... }
}Expand description
A trait for implementing custom merge operations in SlateDB.
The MergeOperator allows applications to bypass the traditional read/modify/update cycle in performance-critical situations where computation can be expressed using an associative operator. This is particularly useful for implementing:
- Aggregations (e.g., counters, sums)
- Buffering (e.g., append-only lists)
§Associativity Requirement
The merge operation MUST be associative, meaning that for any values a, b, and c: merge(merge(a, b), c) == merge(a, merge(b, c))
§Examples
Here’s an example of a counter merge operator:
use bytes::Bytes;
use slatedb::{MergeOperator, MergeOperatorError};
struct CounterMergeOperator;
impl MergeOperator for CounterMergeOperator {
fn merge(&self, _key: &Bytes, existing_value: Option<Bytes>, operand: Bytes) -> Result<Bytes, MergeOperatorError> {
let existing = existing_value
.map(|v| u64::from_le_bytes(v.as_ref().try_into().unwrap()))
.unwrap_or(0);
let increment = u64::from_le_bytes(operand.as_ref().try_into().unwrap());
Ok(Bytes::copy_from_slice(&(existing + increment).to_le_bytes()))
}
fn merge_batch(&self, _key: &Bytes, existing_value: Option<Bytes>, operands: &[Bytes]) -> Result<Bytes, MergeOperatorError> {
let mut total = existing_value
.map(|v| u64::from_le_bytes(v.as_ref().try_into().unwrap()))
.unwrap_or(0);
for operand in operands {
let increment = u64::from_le_bytes(operand.as_ref().try_into().unwrap());
total += increment;
}
Ok(Bytes::copy_from_slice(&total.to_le_bytes()))
}
}Required Methods§
Sourcefn merge(
&self,
key: &Bytes,
existing_value: Option<Bytes>,
value: Bytes,
) -> Result<Bytes, MergeOperatorError>
fn merge( &self, key: &Bytes, existing_value: Option<Bytes>, value: Bytes, ) -> Result<Bytes, MergeOperatorError>
Merges the existing value with a new value to produce a combined result.
This method is called during reads and compactions to combine multiple merge operands into a single value. The implementation must be associative to ensure correct behavior.
§Arguments
key- The key of the entryexisting_value- The current accumulated valuevalue- The new value to merge with the existing value
§Returns
Ok(Bytes)- The merged result as bytesErr(MergeOperatorError)- If the merge operation fails
Provided Methods§
Sourcefn merge_batch(
&self,
key: &Bytes,
existing_value: Option<Bytes>,
operands: &[Bytes],
) -> Result<Bytes, MergeOperatorError>
fn merge_batch( &self, key: &Bytes, existing_value: Option<Bytes>, operands: &[Bytes], ) -> Result<Bytes, MergeOperatorError>
Merges a batch of operands with an optional existing value.
This method allows for more efficient batch processing of merge operands. The default implementation applies pairwise merging, but implementations can override this for better performance (e.g., a counter can sum all values at once).
§Arguments
key- The key of the entryexisting_value- The current accumulated value (if any)operands- A slice of operands to merge, ordered from oldest to newest
§Returns
Ok(Bytes)- The merged result as bytesErr(MergeOperatorError)- If the merge operation fails
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".