MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / asof_join_keyed

Function asof_join_keyed

nodedb/src/engine/timeseries/asof_join.rs:76–129  ·  view source on GitHub ↗

ASOF join with multiple key columns. Groups both sides by key, then performs per-group ASOF join. `key_fn` extracts the grouping key from each row's data.

(
    left: &[TimestampedRow<L>],
    right: &[TimestampedRow<R>],
    tolerance_ms: i64,
    left_key: impl Fn(&L) -> K,
    right_key: impl Fn(&R) -> K,
)

Source from the content-addressed store, hash-verified

74/// Groups both sides by key, then performs per-group ASOF join.
75/// `key_fn` extracts the grouping key from each row's data.
76pub fn asof_join_keyed<L, R, K>(
77 left: &[TimestampedRow<L>],
78 right: &[TimestampedRow<R>],
79 tolerance_ms: i64,
80 left_key: impl Fn(&L) -> K,
81 right_key: impl Fn(&R) -> K,
82) -> Vec<AsofMatch<L, R>>
83where
84 L: Clone,
85 R: Clone,
86 K: Eq + std::hash::Hash + Clone,
87{
88 use std::collections::HashMap;
89
90 // Group right side by key.
91 let mut right_groups: HashMap<K, Vec<&TimestampedRow<R>>> = HashMap::new();
92 for row in right {
93 right_groups
94 .entry(right_key(&row.data))
95 .or_default()
96 .push(row);
97 }
98
99 let mut results = Vec::with_capacity(left.len());
100
101 for left_row in left {
102 let key = left_key(&left_row.data);
103 let matched = if let Some(group) = right_groups.get(&key) {
104 // Binary search for largest timestamp <= left timestamp.
105 let target = left_row.timestamp_ms;
106 let pos = group.partition_point(|r| r.timestamp_ms <= target);
107 if pos > 0 {
108 let candidate = group[pos - 1];
109 let gap = target - candidate.timestamp_ms;
110 if tolerance_ms == i64::MAX || gap <= tolerance_ms {
111 Some(candidate.clone())
112 } else {
113 None
114 }
115 } else {
116 None
117 }
118 } else {
119 None
120 };
121
122 results.push(AsofMatch {
123 left: left_row.clone(),
124 right: matched,
125 });
126 }
127
128 results
129}
130
131#[cfg(test)]
132mod tests {

Callers 1

keyed_asof_joinFunction · 0.85

Calls 5

entryMethod · 0.80
pushMethod · 0.45
lenMethod · 0.45
getMethod · 0.45
cloneMethod · 0.45

Tested by 1

keyed_asof_joinFunction · 0.68