Skip to main content

Data Comparison

🔍

Data Comparison

Reconcile two datasets on composite keys

The Data Comparison node compares a source dataset against a target dataset and reports how they differ. Records are matched on one or more composite key fields, then compared field by field. The result classifies every record as matched, mismatched, missing, extra, or duplicated — making the node well suited to reconciliation, migration validation, and data-quality checks.

Common uses include:

  • Reconciling records between two systems after a migration.
  • Validating that an export matches its source of truth.
  • Detecting rows that exist in one dataset but not the other.
  • Flagging fields whose values differ between source and target.

Before You Start​

What you may needWhere to set it upWhy it matters
The datasets to compareFilesReference each dataset by path or file id when comparing files rather than inline data.
Common key and field namesGlobal VariablesKeep uniqueKeys and field lists consistent across comparison workflows.

Actions​

ActionDescription
dataComparison:compareDataCompare a source dataset against a target dataset on composite keys

dataComparison:compareData​

Compares the source and target datasets record by record. Each record is identified by the combination of uniqueKeys; matched records are then compared on fieldsToCompare (or all shared fields). Optional normalization makes the comparison tolerant of case or whitespace differences. All configuration lives under the config.dataCompareDetails root.

Datasets can be supplied inline, or read from files. When reading from files, the supported types are .json, .csv, .xlsx, and .xls.

Parameters

ParameterTypeRequiredDefaultDescription
inputModestringNorawHow datasets are supplied: raw, filePath, or fileId
normalizationstringNononeValue normalization before comparison: none, case, whitespace, or both
uniqueKeysarray or CSVYes--Composite key fields used to match records. Empty produces a VALIDATION_ERROR
fieldsToComparearray or CSVNoall shared fieldsFields compared on matched records
fieldMappingsobjectNo{}Map of source field name to target field name
sourceDataJSON arrayIf inputMode is raw--Inline source records
targetDataJSON arrayIf inputMode is raw--Inline target records
sourceFilepathIf inputMode is filePath--Source dataset path (read via the artifact client)
targetFilepathIf inputMode is filePath--Target dataset path (read via the artifact client)
sourceFileIdstringIf inputMode is fileId--Source file identifier (read via the web client helper)
targetFileIdstringIf inputMode is fileId--Target file identifier (read via the web client helper)

Example: Reconcile customer records after a migration

FieldValue
inputModeraw
uniqueKeyscustomerId
fieldsToComparename, status
normalizationboth
sourceData[{"customerId": "1", "name": "Acme", "status": "active"}]
targetData[{"customerId": "1", "name": "acme ", "status": "active"}]

What happens:

  1. The node keys both datasets by customerId.
  2. It normalizes values for case and whitespace before comparing.
  3. Record 1 matches on the key and compares equal on name and status.
  4. The record is reported as matched; the brief and detailed results summarize the outcome.

Output​

The action returns a JSON result with a summary (briefResult) and a per-record breakdown (detailedResult).

FieldTypeDescription
briefResult.isSuccessbooleantrue when the comparison completed
briefResult.resultstringOverall outcome of the comparison
briefResult.sourceRecordsintegerNumber of records in the source dataset
briefResult.targetRecordsintegerNumber of records in the target dataset
briefResult.matchedintegerRecords present in both with equal compared fields
briefResult.mismatchesintegerRecords present in both but with differing fields
briefResult.missingintegerRecords in the source but not the target
briefResult.extraintegerRecords in the target but not the source
briefResult.duplicatesintegerRecords with duplicate composite keys
detailedResultarrayPer-record comparison detail

Example output:

{
"briefResult": {
"isSuccess": true,
"result": "COMPLETED",
"sourceRecords": 100,
"targetRecords": 98,
"matched": 95,
"mismatches": 3,
"missing": 2,
"extra": 0,
"duplicates": 0
},
"detailedResult": [
{"key": "1001", "status": "matched"},
{"key": "1002", "status": "mismatch", "fields": {"status": {"source": "active", "target": "inactive"}}}
]
}

Common Error Scenarios​

ErrorLikely CauseWhat to Check
VALIDATION_ERRORuniqueKeys is empty, or a required dataset input is missingProvide at least one unique key and the source/target inputs for the chosen inputMode
VALIDATION_ERRORinputMode set but matching inputs not suppliedSupply sourceData/targetData for raw, sourceFile/targetFile for filePath, or sourceFileId/targetFileId for fileId
COMPARISON_ERRORA file could not be read or parsedConfirm the file exists and is a supported type (.json, .csv, .xlsx, .xls). Retry if the failure is transient

Best Practices​

  • Choose keys that are truly unique. Composite keys with duplicates inflate the duplicates count and skew matching. Combine fields until each record is uniquely identified.
  • Normalize when sources disagree on formatting. Use case or both when the same value appears with different casing or trailing spaces across systems.
  • Limit compared fields. Set fieldsToCompare to the fields that matter so incidental differences (timestamps, ids) do not register as mismatches.
  • Map renamed columns. Use fieldMappings when source and target label the same data differently, so records still align.
  • Read the brief first. briefResult gives the reconciliation at a glance; drill into detailedResult only for the records that differ.