|
| 1 | +--- |
| 2 | +'@objectstack/objectql': patch |
| 3 | +--- |
| 4 | + |
| 5 | +fix(objectql): a per-aggregation `filter` with `$contains` / `$notContains` on a multi-valued field counts the rows the same `where` finds (#20873) |
| 6 | + |
| 7 | +Clause-②: no |
| 8 | + |
| 9 | +`engine.aggregate({ aggregations: [{ …, filter }] })` — and so `POST /api/v1/data/:object/query` |
| 10 | +with a per-aggregation `filter` — evaluates that filter in the engine, not in the driver. Its |
| 11 | +`$contains` arm failed every value that was not a string, so on a `multiple: true` lookup, |
| 12 | +`multiselect`, `checkboxes` or `tags` field a stored array never matched: |
| 13 | +`{ owners: { $contains: 'u1' } }` counted 0 on every driver where the same condition as a `where` |
| 14 | +found 2 rows, and `$notContains` counted every row, the rows holding the member included. |
| 15 | + |
| 16 | +On a declared JSON-stored field (a multi-valued field, or a structured-JSON type) both operators |
| 17 | +now ask MEMBERSHIP, the reading `FILTER_OPERATORS`' `$contains` docblock declares and `where` gives |
| 18 | +on every SQL dialect: `'u1'` is a member of `['u1', 'u2']` and not of `['u10']`, and a member stored |
| 19 | +as a number or boolean is named by its text (`'1'` finds `[1, 2]`). `$notContains` is the exact |
| 20 | +complement, and a row with no value still satisfies it. A scalar text field keeps the substring |
| 21 | +test, unchanged, and so does `having`. |
| 22 | + |
| 23 | +No query that was refused now answers, and none that answered is refused: only the count of a |
| 24 | +per-aggregation `filter` on a multi-valued field moves, to the `where` count. |
0 commit comments