15 minlesson

Query Building: Step-by-Step

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:

bash
1npx cxtms gql types --filter order

Example output:

1OrderGqlDto
2OrderEntityGqlDto
3CreateOrderInput
4UpdateOrderInput
5OrderFilterInput

The type for querying order records is OrderGqlDto.


Step 2: Inspect the Type's Fields

Now inspect OrderGqlDto to see every available field:

bash
1npx cxtms gql type OrderGqlDto

Example output (truncated):

1OrderGqlDto
2 orderId Int!
3 orderNumber String
4 orderType String
5 status String
6 created DateTime
7 lastModified DateTime
8 orderEntities [OrderEntityGqlDto]
9 customValues JSON
10 changeHistory EntityAuditHistoryLightResult
11 ...

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:

bash
1npx cxtms query '{
2 orders(organizationId: 1, take: 5) {
3 items {
4 orderId
5 orderNumber
6 status
7 orderType
8 }
9 totalCount
10 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:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "orderType:ParcelShipment AND status:Active"
5 take: 10
6 ) {
7 items {
8 orderId
9 orderNumber
10 status
11 }
12 totalCount
13 }
14}'

Try a wildcard to find orders with a known prefix:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "orderNumber:ORD-2026*"
5 take: 10
6 ) {
7 items {
8 orderId
9 orderNumber
10 created
11 }
12 totalCount
13 }
14}'

Step 5: Add Sorting

Sort results to surface the most recently modified orders first, with a secondary sort by order number:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "orderType:ParcelShipment"
5 orderBy: "-lastModified,orderNumber"
6 take: 10
7 ) {
8 items {
9 orderId
10 orderNumber
11 lastModified
12 }
13 totalCount
14 }
15}'

If order numbers are strings but you want numeric ordering, append ~ToInt32:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 orderBy: "-created,orderId~ToInt32"
5 take: 10
6 ) {
7 items { orderId orderNumber created }
8 totalCount
9 }
10}'

Step 6: Paginate Results

Fetch the second page of 25 results (skip the first 25):

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "status:Active"
5 orderBy: "-created"
6 take: 25
7 skip: 25
8 ) {
9 items {
10 orderId
11 orderNumber
12 status
13 }
14 totalCount
15 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:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "orderId:196596"
5 take: 1
6 ) {
7 items {
8 orderId
9 orderNumber
10 customValues
11 }
12 }
13}'

To find orders where a specific custom field is missing:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "customValues.po:NULL"
5 take: 20
6 ) {
7 items {
8 orderId
9 orderNumber
10 customValues
11 }
12 totalCount
13 }
14}'

To find orders with a specific custom field value:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "customValues.incoterm:EXW AND status:Active"
5 take: 20
6 ) {
7 items {
8 orderId
9 orderNumber
10 customValues
11 }
12 totalCount
13 }
14}'

Step 8: Query Audit Change History

Add changeHistory to an entity query to see who changed it and what they changed:

bash
1npx cxtms query '{
2 orders(
3 organizationId: 1
4 filter: "orderId:196596"
5 take: 1
6 ) {
7 items {
8 orderId
9 orderNumber
10 changeHistory(maxResults: 10) {
11 entityName
12 hasMoreRecords
13 changes {
14 state
15 timestamp
16 user {
17 fullName
18 email
19 }
20 changedFields {
21 fieldName
22 originalValue
23 currentValue
24 fieldType
25 }
26 }
27 }
28 }
29 }
30}'

To search audit history across all orders for a specific user, use the root auditChanges query:

bash
1npx cxtms query '{
2 auditChanges(
3 organizationId: 1
4 filter: "entityName:Order AND userId:user-abc-123"
5 orderBy: "-timestamp"
6 take: 20
7 ) {
8 items {
9 state
10 timestamp
11 user { fullName email }
12 changedFields {
13 fieldName
14 originalValue
15 currentValue
16 }
17 }
18 }
19}'

Summary: The Query-Building Workflow

  1. Discover the typenpx cxtms gql types --filter <term>
  2. Inspect fieldsnpx cxtms gql type <TypeName>
  3. Write a basic query — minimal fields, no filter, verify the response shape
  4. Add a filter — Lucene syntax: field:value, field:prefix*, AND/OR/NOT
  5. Add sortingorderBy: "field" or orderBy: "-field", use ~ToInt32 for numeric strings
  6. Paginatetake and skip; check pageInfo.hasNextPage to stop
  7. Query customValues — request the dictionary, filter on keys with dot notation
  8. Check change historychangeHistory on items, or auditChanges root 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.

Query Building: Step-by-Step - Anko Academy