Skip to Content
MappingsCross-resource lookups

Cross-resource lookups

Sometimes the value a mapping needs lives on another resource. A common example: a gift card export only carries the ID of the order it was bought with — the owning customer is two steps away:

gift card → its order → the order's customer

A lookup follows those links for you. You build them on the editor’s Lookups tab; they are published, versioned, and previewed together with the mapping expression.

Building a lookup

A lookup reads as a sentence, left to right. Start from a field on the row you’re mapping, then follow it to another resource — as many times as you need:

Start from BOUGHT_BY_ORDER_ID on this gift card → find the order with that ID, take its CustomerId → find the customer with that ID, take its Shopify ID

Each step has two choices:

  • Resource — where the step looks (order, customer, …). The step matches on the referenced record’s original ID: the same ID your source data uses to point at it.
  • What to take — either a field from that record’s source data (CustomerId above), which becomes the next step’s ID to match on, or its Shopify ID, the ID your destination store assigned once that record migrated. Taking the Shopify ID is normally the last step.

Start typing in a field box and it suggests matching fields, showing each one’s value on the current sample row beside it — so you can pick a field by what it holds rather than guessing at names. A field that isn’t in the sample can still be typed in full.

Name the lookup whatever reads best — that name is how you use it in the mapping:

{ "code": CODE, "customer_id": $._refs.customer_gid }

The Insert button drops that reference in at your cursor.

If the starting field holds a list (e.g. a product’s category IDs), the lookup resolves every entry and returns a list.

Fields that repeat, like line items

An order’s line items each name their own product, and every one of them needs its own Shopify ID. Start the lookup from the field as it sits inside the list — Items.ProductId — and the lookup offers a second choice:

  • All of them, as one list — every entry resolved, gathered into a single list. Good for something the record needs as a set.
  • One per entry, matched back by ID — the lookup resolves them all and hands back a table you can read inside the list, so each line item picks up the value for its own ID:
{ "lineItems": Items.{ "quantity": Qty, "productId": $lookup($$._refs.product_gid, $string(ProductId)) } }

The Insert button writes that form for you. Note the double $$: it means “the row I’m mapping”, which you need because inside the list a single $ refers to the line item you’re on.

Pick the second option whenever the value belongs to the entry rather than to the record as a whole. A list can’t do that job: if two of five products haven’t migrated yet, the list comes back with three values and nothing to say which lines they belong to. Matching by ID keeps every line item with its own product, and a line whose product isn’t there yet simply migrates without the link.

Renaming a lookup does not update expressions that already use it. If you rename one, update the $._refs.<name> references in the mapping to match.

Live preview

With a sample row selected, each lookup shows what it resolves to for that row, using your migration’s real extracted and migrated data — so you can confirm a chain works before publishing. A step that finds nothing shows no match. The Output and Preview tabs use the same resolved values, so what you see is what a run will produce.

A lookup can only resolve what exists: the referenced resource must be extracted (for field values) or already migrated (for Shopify IDs). Rows whose references can’t be resolved yet still migrate — the field is simply left out, and the record shows a warning you can review under the resource’s records. A later run fills the value in automatically once the referenced record has landed.

$mapLookup for computed keys

When a chain isn’t enough — say the ID to match on has to be assembled from two fields — you can resolve a single step directly inside the mapping:

{ "customer_id": $mapLookup("customer_shopify_id", $.someComputedId) }

The first argument names one step of a lookup you’ve already built. The Lookups tab lists the available names under Advanced; publishing rejects anything else, and the name must be quoted rather than computed.

Ordering between resources

Building a lookup also tells Graftport that this resource depends on the one it reads: runs schedule the referenced resource ahead of the one referencing it, so chains resolve on the first pass whenever possible.

Last updated on