Skip to content

driver-mongodb lowers avg / sum over a boolean column to null / 0 — the same cell as #11065, one driver over #11151

Description

@os-zhuang

Found while fixing #11065 in driver-memory. Filed unassigned, not fixed — #11065's dispatch scoped the fix to driver-memory and said explicitly that any other driver found sharing the defect is to be reported rather than repaired in that PR.

What was read

packages/drivers/driver-mongodb/src/mongodb-aggregation.ts lowers the two arithmetic aggregates as bare accumulators:

case'sum':
return{$sum: fieldRef??0};case'avg':
return{$avg: fieldRef??0};

That is the same expression shape driver-memory's analytics face carried before #11065, and MongoDB's $avg / $sum ignore a non-numeric value — a boolean included. So over a boolean column this should answer null for avg and 0 for sum, while every SQL face answers the arithmetic numbers (AVG(col) = 0.4 and SUM(col) = 2 over #11065's five rows) and objectql's in-memory fallback answers those same numbers, because its toNumber is Number(v) and Number(true) === 1.

The count arm immediately above it was already special-cased for exactly this family of divergence (#6814), which is some evidence that the bare accumulators below it were simply not revisited.

What was NOT established, and by whom it should be

⚠️This was not executed against a live MongoDB. It is a reading of the lowering plus MongoDB's documented accumulator semantics, cross-checked against mingo 7.2.4 (this repo's in-memory mingo answered {avg: null, sum: 0} over five booleans, and mingo mirrors MongoDB here). mingo is not MongoDB, so the value should be confirmed on a real server — or through whatever server-free evaluation half this driver uses (#5517) — before anyone changes the lowering.

If confirmed, the fix has a worked precedent to copy: #11065 wrapped the field reference in a boolean-only coercion, leaving null, missing and non-numeric strings to be ignored by the accumulator exactly as before.

{$cond: [{$eq: [{$type: path},'bool']},{$cond: [path,1,0]},path]}

Why it is worth a card

Same reason as #11065: neither value is an error, so a dashboard tile bound to a rate measure renders a percentage under SQL and a blank here, indistinguishable from "no matching rows"; and sum's 0 is worse than avg's null, being a plausible number rather than a visible hole. The severity call belongs to triage — I am recording the cell, not proposing a priority.

Related: #11065 (this cell on driver-memory, fixed), #6814 / #6815 (earlier cells of the same "drivers disagree about an aggregate" family, both closed).

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions