Extract a numeric value for an aggregate function from the event. For COUNT, always returns 1.0 (each event counts as one). For SUM/MIN/MAX/AVG, parses the input expression as a field path and extracts the numeric value from new_value.
(event: &CdcEvent, func: AggFunction, input_expr: &str)
| 158 | /// For SUM/MIN/MAX/AVG, parses the input expression as a field path |
| 159 | /// and extracts the numeric value from new_value. |
| 160 | fn extract_agg_value(event: &CdcEvent, func: AggFunction, input_expr: &str) -> f64 { |
| 161 | if func == AggFunction::Count { |
| 162 | return 1.0; // Each event counts as one. |
| 163 | } |
| 164 | |
| 165 | // Parse input_expr as a field name (simple case). |
| 166 | // Supports: "field_name" or "doc_get(new_value, '$.field')". |
| 167 | let field_name = if input_expr.contains("doc_get") { |
| 168 | // Extract field path from doc_get(new_value, '$.field'). |
| 169 | input_expr |
| 170 | .split("'$.") |
| 171 | .nth(1) |
| 172 | .and_then(|s| s.split('\'').next()) |
| 173 | .unwrap_or(input_expr) |
| 174 | } else { |
| 175 | input_expr.trim() |
| 176 | }; |
| 177 | |
| 178 | // Look up the field in new_value. |
| 179 | event |
| 180 | .new_value |
| 181 | .as_ref() |
| 182 | .and_then(|v| v.get(field_name)) |
| 183 | .and_then(|v| match v { |
| 184 | serde_json::Value::Number(n) => n.as_f64(), |
| 185 | serde_json::Value::String(s) => s.parse::<f64>().ok(), |
| 186 | _ => None, |
| 187 | }) |
| 188 | .unwrap_or(f64::NAN) // NaN → skipped by GroupState::update. |
| 189 | } |
| 190 | |
| 191 | #[cfg(test)] |
| 192 | mod tests { |