Docs · Concepts
Aggregations
The object that does the comparing — keys, measures, the five operators, and how rows are matched.
An aggregation is the comparison itself. It takes two or more sources, lines their rows up on shared keys, and compares the measures. A Check shows one aggregation's result.
On screen you will also see the word Comparison for the same thing, in the Builder and on the canvas.
#Keys
Grouping keys are what makes a row on one side the same row as a row on the other. Rows from every source are aligned on these columns.
Choosing them is the single most consequential decision in a Check. Too few and unrelated rows collide into one. Too many and nothing matches at all.
#Measures
Measures are the values compared side by side. Each has two settings worth knowing:
- Compare — turn it off to carry the figure through without diffing it.
- Tolerance — the absolute difference still counted as a match. A rounding difference of a cent is not a reconciliation problem.
Each input says how its column becomes the measure, using one of SUM, COUNT, MIN, MAX, AVG or FIRST.
#Carried columns
Columns to show that are neither joined on nor counted — a document date, an order number, a status. Map each source's own column onto one name, and the result carries a single column filled from whichever source produced the row.
Where aggregation collapsed several rows into one, the first value wins.
#Sources and the baseline
Each input maps its own columns onto the keys and measures. The first input is the baseline that every delta and verdict is measured against; tick another to change it.
An input can also read another aggregation of the same Check, which is how a multi-stage comparison is built.
#The five operators
The operator decides which join is performed, and therefore which keys reach the output.
| Operator | Join | Keys in the output | Compares? |
|---|---|---|---|
| COMPARE | Full outer | Every key in any input | Yes |
| OVERLAP | Inner | Only keys every input has | Yes |
| ENRICH | Left | The first input's | No |
| EXCEPTIONS | Left anti | The first input's, minus those every other also has | No |
| APPEND | Union all | Not a join — rows are stacked | No |
COMPARE is the one you want for a reconciliation: every key from every source, with the deltas and the verdict for each one.
APPEND deserves a warning it gives you itself: there is no verdict column, and two rows with the same key stay two rows.
#How rows are matched
Exact match on the key tuple, after the key's rules have been applied.
Matching is case-sensitive by default. Strings are trimmed but never case-folded. The reasoning is worth repeating: store codes differing only by case are far more likely to be a real data problem than a formatting artefact, and silently merging them would hide exactly what Mosaic exists to reveal. If you want case-insensitive matching, add UPPERCASE or lowercase to that key's rule — an explicit decision rather than a silent one.
One exception: a full timestamp is re-spelled to a single canonical form, so three notations of one moment become one key. A date-only value like 2026-03-01 is deliberately not treated that way — it is a label rather than a moment, and it is exactly what Date only produces.
A row whose key comes out null or blank is dropped when aligning and kept when stacking. Every run says how many: "Input "POS": 3 row(s) had a null or empty key and were excluded from the join."
#Matching nearby records
After exact matching, an aggregation can optionally align unambiguous records by time and value — for settlement data where the two systems timestamp the same transaction seconds apart. Other key fields must still agree. You set a time window, a value tolerance, a minimum confidence and an ambiguity margin, and a row matched this way is labelled probable with its confidence.
#The three verdicts
| Verdict | Meaning |
|---|---|
| Match | Every compared measure agrees, within tolerance, across every input that has the key |
| Different | The key is on both sides and at least one measure disagrees beyond tolerance |
| Missing | The row exists in one input and not another |
Three more states are kept deliberately outside the verdict, because none of them means the systems disagree:
- Unable to connect — a source could not be reached for that row.
- Not read — row limit — the comparison stopped before reaching it.
- Known — somebody marked this difference as understood. It stays a difference; it just stops being new.
A summary also counts rows excluded for having no key.
#Reading the result table
Columns are badged by what they are: KEY, MEASURE, DELTA, STATUS, LINEAGE, SOURCE, COMPUTED, FROM and Carried.
#Mapping, and the two views
The aggregation editor has five tabs: Mapping, Normalise, Rules, Settings and Result.
Inside Mapping are two views of the same thing:
Flow — the sources, the comparison and the table it produces, drawn as a canvas with numbered steps. Use it to understand the shape, and to reach the Keys & measures section where the canonical columns are defined.
Mapping — each source's own columns, fitted to the canonical ones, as a grid. Use it to do the fitting. It badges how many cells are still empty and offers Map by name to fill the obvious ones. It tells you when you are done: "Every source feeds every canonical column."
Each row in the grid says what it is for: a key — what rows are matched on, a measure — a figure compared across sources, carried through, shown and not compared.
#Other settings
Rows to leave out — a cancelled document is not a discrepancy. Exclusions are applied before the key check, and every run says how many were removed. The tests are is, is not, contains, is blank and is not blank, compared case-insensitively.
Group in the database — pushes the grouping down to the source system instead of doing it in Mosaic.
Impact measure — ranks outstanding exceptions by the largest absolute discrepancy on the measure you name. Choose the one denominated in money.