Related Orders
CXTMS tracks relationships between orders through shared commodities. Two orders are related when they share any commodity on the same root-to-leaf path of the container tree — meaning one order's commodity is an ancestor, equal to, or descendant of a commodity owned by another order.
All related-order fields are available on the Order type and support optional filtering
and sorting.
Fields
| Field | Returns | DataLoader |
|---|---|---|
allRelatedOrders | [Order] | vw_order_related_orders_v3 (organization-scoped) |
relatedOrders | [Order] | Alias of allRelatedOrders |
relatedOrder | Order | First result only |
relatedOrdersV3 | [Order] | Compatibility alias of relatedOrders |
relatedOrderV3 | Order | Compatibility alias of relatedOrder |
The temporary relatedOrdersV2 and relatedOrderV2 fields have been removed. The V3
aliases remain for production modules created during the rollout, but new configuration
should use allRelatedOrders, relatedOrders, or relatedOrder.
Arguments
All five fields accept the same arguments:
| Argument | Type | Required | Description |
|---|---|---|---|
filter | String | No | Lucene filter applied to the related orders at the database level |
orderBy | String | No | Sort expression (e.g. orderNumber asc, created desc). Defaults to orderNumber |
relatedOrders and allRelatedOrders
Both fields return all orders related to the parent order. They use the same
AllRelatedOrdersDataLoader and the same organization-scoped
vw_order_related_orders_v3 relation used by property-path filtering and sorting.
allRelatedOrders is also the preferred navigation name in new filterByProperty and
orderByProperty configuration.
query {
getOrders(organizationId: 1, take: 5) {
items {
orderId
orderNumber
relatedOrders(filter: "orderType:Shipment", orderBy: "created desc") {
orderId
orderNumber
orderType
}
}
}
}
relatedOrder
Returns only the first related order matching the filter and sort criteria. Backed by
the same DataLoader as relatedOrders; identical performance characteristics.
query {
getOrders(organizationId: 1, take: 10) {
items {
orderId
orderNumber
relatedOrder(orderBy: "created desc") {
orderId
orderNumber
created
}
}
}
}
relatedOrdersV3 and relatedOrderV3
These are compatibility aliases for relatedOrders and relatedOrder. All names now
resolve pairs through vw_order_related_orders_v3. The view reads a trigger-maintained
commodity-kinship table, so it does not walk the container tree for each request. Pair
discovery and the final Order query are organization-scoped, preventing a commodity
link that crosses organization boundaries from exposing another organization's orders.
The GraphQL resolver, filtering, and sorting all use this same view and therefore share one definition of "related." This also makes V3 paths usable before paging:
relatedOrdersV3[relatedOrder.orderType:BookingOrder].relatedOrder.trackingNumber
The view excludes draft related orders and has no container-depth limit. Commodity-tree changes maintain the kinship table through database triggers, and PostgreSQL can push the caller's filter or sort predicate into the view. This avoids the full-table recursive work performed by the legacy view while keeping list, filter, and sort results aligned.
relatedOrdersV3 returns every matching order. relatedOrderV3 returns the first result
after applying filter and orderBy.
query {
getOrders(organizationId: 1, take: 5) {
items {
orderId
orderNumber
relatedOrdersV3(filter: "orderType:Shipment", orderBy: "created desc") {
orderId
orderNumber
orderType
}
}
}
}
DataLoader batching
All five fields share the same batching strategy. Requests within a single GraphQL
operation that have identical (organizationId, filter, orderBy) arguments are
grouped. Pair resolution reads the organization-scoped view for the whole batch in one
query:
- Resolve
(OrderId, RelatedOrderId)pairs for all batched orders. - Group the pair-resolution results by
(organizationId, filter, orderBy)and fetch the matchingOrderrows once per unique combination. - Project
Order → OrderGqlDtousing AutoMapper and return the results to each caller.
This means fetching related orders for 50 orders in a list view costs the same as fetching them for 1 — as long as the filter and sort arguments are consistent.
Property-path filtering and sorting
The Order entity exposes both allRelatedOrders and relatedOrdersV3 navigations over
the same view so existing module paths continue to work. Prefer the unversioned form:
allRelatedOrders[relatedOrder.orderType:BookingOrder].relatedOrder.trackingNumber
Related topics
- Filter syntax — Lucene filter expressions
- Sorting —
orderByconventions