Query Building: Step-by-Step
This lesson walks you through a complete, practical query-building workflow. Starting from "I need order data" through schema discovery, filtering, sorting, pagination, customValues access, and finally audit history — you will follow the same process you will use every day when working with CXTMS.
Replace organizationId: 1 with your actual organization ID throughout these steps.
Step 1: Discover the Type
Before writing any query, find the name of the type you want to query. Use gql types with a filter:
bash1npx cxtms gql types --filter order
Example output:
1OrderGqlDto2OrderEntityGqlDto3CreateOrderInput4UpdateOrderInput5OrderFilterInput
The type for querying order records is OrderGqlDto.
Step 2: Inspect the Type's Fields
Now inspect OrderGqlDto to see every available field:
bash1npx cxtms gql type OrderGqlDto
Example output (truncated):
1OrderGqlDto2 orderId Int!3 orderNumber String4 orderType String5 status String6 created DateTime7 lastModified DateTime8 orderEntities [OrderEntityGqlDto]9 customValues JSON10 changeHistory EntityAuditHistoryLightResult11 ...
This tells you the exact field names and their types. Do not guess — field names in the filter must match exactly.
Step 3: Write a Basic Query
With confirmed field names, write the simplest working query:
bash1npx cxtms query '{2 orders(organizationId: 1, take: 5) {3 items {4 orderId5 orderNumber6 status7 orderType8 }9 totalCount10 pageInfo { hasNextPage hasPreviousPage }11 }12}'
Verify the response shape — items, totalCount, and pageInfo should all be present.
Step 4: Add a Filter
Narrow results to a specific order type and status using Lucene filter syntax:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "orderType:ParcelShipment AND status:Active"5 take: 106 ) {7 items {8 orderId9 orderNumber10 status11 }12 totalCount13 }14}'
Try a wildcard to find orders with a known prefix:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "orderNumber:ORD-2026*"5 take: 106 ) {7 items {8 orderId9 orderNumber10 created11 }12 totalCount13 }14}'
Step 5: Add Sorting
Sort results to surface the most recently modified orders first, with a secondary sort by order number:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "orderType:ParcelShipment"5 orderBy: "-lastModified,orderNumber"6 take: 107 ) {8 items {9 orderId10 orderNumber11 lastModified12 }13 totalCount14 }15}'
If order numbers are strings but you want numeric ordering, append ~ToInt32:
bash1npx cxtms query '{2 orders(3 organizationId: 14 orderBy: "-created,orderId~ToInt32"5 take: 106 ) {7 items { orderId orderNumber created }8 totalCount9 }10}'
Step 6: Paginate Results
Fetch the second page of 25 results (skip the first 25):
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "status:Active"5 orderBy: "-created"6 take: 257 skip: 258 ) {9 items {10 orderId11 orderNumber12 status13 }14 totalCount15 pageInfo { hasNextPage hasPreviousPage }16 }17}'
Use totalCount to compute total pages:
totalPages = Math.ceil(totalCount / 25)
Stop fetching when pageInfo.hasNextPage is false.
Step 7: Query customValues
customValues is a JSON dictionary. Request the whole dictionary or filter on specific keys:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "orderId:196596"5 take: 16 ) {7 items {8 orderId9 orderNumber10 customValues11 }12 }13}'
To find orders where a specific custom field is missing:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "customValues.po:NULL"5 take: 206 ) {7 items {8 orderId9 orderNumber10 customValues11 }12 totalCount13 }14}'
To find orders with a specific custom field value:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "customValues.incoterm:EXW AND status:Active"5 take: 206 ) {7 items {8 orderId9 orderNumber10 customValues11 }12 totalCount13 }14}'
Step 8: Query Audit Change History
Add changeHistory to an entity query to see who changed it and what they changed:
bash1npx cxtms query '{2 orders(3 organizationId: 14 filter: "orderId:196596"5 take: 16 ) {7 items {8 orderId9 orderNumber10 changeHistory(maxResults: 10) {11 entityName12 hasMoreRecords13 changes {14 state15 timestamp16 user {17 fullName18 email19 }20 changedFields {21 fieldName22 originalValue23 currentValue24 fieldType25 }26 }27 }28 }29 }30}'
To search audit history across all orders for a specific user, use the root auditChanges query:
bash1npx cxtms query '{2 auditChanges(3 organizationId: 14 filter: "entityName:Order AND userId:user-abc-123"5 orderBy: "-timestamp"6 take: 207 ) {8 items {9 state10 timestamp11 user { fullName email }12 changedFields {13 fieldName14 originalValue15 currentValue16 }17 }18 }19}'
Summary: The Query-Building Workflow
- Discover the type —
npx cxtms gql types --filter <term> - Inspect fields —
npx cxtms gql type <TypeName> - Write a basic query — minimal fields, no filter, verify the response shape
- Add a filter — Lucene syntax:
field:value,field:prefix*,AND/OR/NOT - Add sorting —
orderBy: "field"ororderBy: "-field", use~ToInt32for numeric strings - Paginate —
takeandskip; checkpageInfo.hasNextPageto stop - Query customValues — request the dictionary, filter on keys with dot notation
- Check change history —
changeHistoryon items, orauditChangesroot query for cross-entity searches
Save complex queries to .graphql files and run them with npx cxtms query my-query.graphql. Use --vars to parameterize queries you run repeatedly with different IDs.