Unified Common Model → qode-matching ES (v3)
Every ATS normalizes to the same Unified candidate shape; this is how it's transformed into our per-connection index — which mirrors qode-matching's v3 candidate schema. indexed fields are what the engine filters and ranks on; display fields ride in _source for the result card (kept via dynamic: false, not in the v3 mapping). Reference only.
Candidate mapping
Source (Unified) → target (ES) → transform.
| Unified Common Model | qode-matching ES (v3) | Transform | In index? |
|---|---|---|---|
| id · external_identifier | id, username | id → both (username mirrors id) | indexed |
| title | jobTitle | copy (keyword) | indexed |
| address.city | city | copy — v3 location field | indexed |
| address.country | country | copy | indexed |
| rawLocation (assembled) | viewport { lat, lon } | resolved via location-ms (null if unresolved) | indexed |
| experiences[] { title, company_name, start_at, end_at } | experiences[] { jobTitle, companyName, durationMonths, isCurrent } | start_at/end_at → durationMonths; no end_at → isCurrent | indexed |
| (derived from experiences) | totalExperienceMonths, avgExperienceDurationMonths | sum · average of durations | indexed |
| education[] { institution, degree, level, field_of_study, end_at } | educations[] { schoolName, degreeType, fieldOfStudy, graduationDate } | institution→schoolName; degree (or level)→degreeType; end_at→graduationDate | indexed |
| skills: string[] | skills[] { name } | one nested entry per skill (keyword) | indexed |
| languages · certifications | languages[], certifications[] | best-effort (Unified rarely provides these) | indexed |
| name · first_name + last_name | fullname | use name, else join first + last | display |
| title | headline | copy | display |
| image_url | avatar | copy | display |
| address.{ city, region, country } | rawLocation | assemble "City, Region, Country" | display |
| skills[] | skills[].canonicalName | = name (display) | display |
| created_at · updated_at | createdAt · updatedAt | ISO 8601 | display |
| emails, telephones, tags, web_url, link_urls, origin, sources… | — | no field in the v3 candidate schema | — |
We don't populate qode-matching's ML-derived v3 fields (dense-vector embeddings, domains, per-experience skills/company enrichment) — those come from qode-matching's own pipeline, not raw ATS data.