Update statistics with a new observed value. Call this on every write (PointPut) for each field in the document.
(&mut self, value: Option<&serde_json::Value>)
| 62 | /// |
| 63 | /// Call this on every write (PointPut) for each field in the document. |
| 64 | pub fn observe(&mut self, value: Option<&serde_json::Value>) { |
| 65 | self.row_count += 1; |
| 66 | |
| 67 | match value { |
| 68 | None | Some(serde_json::Value::Null) => { |
| 69 | self.null_count += 1; |
| 70 | } |
| 71 | Some(val) => { |
| 72 | self.non_null_count += 1; |
| 73 | |
| 74 | // Update min/max. |
| 75 | let val_str = match val { |
| 76 | serde_json::Value::String(s) => s.clone(), |
| 77 | other => other.to_string(), |
| 78 | }; |
| 79 | match &self.min_value { |
| 80 | None => self.min_value = Some(val_str.clone()), |
| 81 | Some(min) if val_str < *min => self.min_value = Some(val_str.clone()), |
| 82 | _ => {} |
| 83 | } |
| 84 | match &self.max_value { |
| 85 | None => self.max_value = Some(val_str.clone()), |
| 86 | Some(max) if val_str > *max => self.max_value = Some(val_str.clone()), |
| 87 | _ => {} |
| 88 | } |
| 89 | |
| 90 | // Update HyperLogLog for cardinality estimation. |
| 91 | let hash = crate::util::fnv1a_hash(val_str.as_bytes()); |
| 92 | let register_idx = (hash as usize) & (DEFAULT_HLL_M - 1); |
| 93 | let remaining = hash >> DEFAULT_HLL_P; |
| 94 | let leading_zeros = if remaining == 0 { |
| 95 | (64 - DEFAULT_HLL_P) as u8 |
| 96 | } else { |
| 97 | remaining.trailing_zeros() as u8 + 1 |
| 98 | }; |
| 99 | if leading_zeros > self.hll_registers[register_idx] { |
| 100 | self.hll_registers[register_idx] = leading_zeros; |
| 101 | } |
| 102 | |
| 103 | // Re-estimate distinct count from HLL registers. |
| 104 | self.distinct_count = self.hll_estimate(); |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | /// HyperLogLog cardinality estimate. |
| 110 | fn hll_estimate(&self) -> u64 { |