Data Search Step

Use this step to search and retrieve records from your organization's datasets. Configure search criteria with filters, sorting, and linked entity relationships. Display results in customizable tables with optional confirmation pages.

Top-level properties

nametyperequiredconstraintsdescription
datasetsarrayyesitems: datasetOne or more dataset search configurations

Dataset

nametyperequiredconstraintsdescription
datasetIdstringyesIdentifier of the dataset to search
setupobjectyestype: DataSearchSetupSearch configuration including criteria and selection mode
resultsobjectyestype: DataSearchResultsResults display configuration

Setup

nametyperequiredconstraintsdescription
requiredbooleanyesWhether a selection is mandatory for workflow continuation
selectionModestringyesenum: AUTOMATIC, MANUALHow results are selected: automatic picks first match, manual requires user selection
primarySearchCriteriaobjectyestype: SearchCriteriaMain search criteria for the primary dataset
linkedEntitiesFiltersobjectyesAdditional filters for linked entities (key: entity identifier, value: SearchCriteria)

Selection Modes

  • AUTOMATIC: Automatically selects the first matching result
  • MANUAL: Requires user to manually select from search results

Search Criteria

nametyperequiredconstraintsdescription
sortFieldIdstringyesField identifier to sort results by
sortDirectionstringyesenum: ASCENDING, DESCENDINGSort order direction
joinLogicstringyesenum: AND, ORHow multiple filters are combined
filtersarrayyesitems: SearchCriteriaFilterArray of filter conditions

Sort Directions

  • ASCENDING: Sort from lowest to highest (A-Z, 0-9)
  • DESCENDING: Sort from highest to lowest (Z-A, 9-0)

Join Logic

  • AND: All filters must match (intersection)
  • OR: Any filter can match (union)

Search Criteria Filter

nametyperequiredconstraintsdescription
fieldIdstringyesnullable: trueField identifier to filter on
operatorstringyesenum: EQUALS, NOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH; nullable: trueComparison operator
valuestringyesnullable: true; supports mapping pattern: {{Step.Field}}Filter value (literal, mapped from workflow data, or empty string)

Operators

  • EQUALS: Exact match
  • NOT_EQUALS: Not equal to value
  • GREATER_THAN: Numeric or date comparison
  • GREATER_THAN_OR_EQUALS: Greater than or equal
  • LESS_THAN: Less than value
  • LESS_THAN_OR_EQUALS: Less than or equal
  • CONTAINS: String contains substring
  • STARTS_WITH: String begins with value
  • ENDS_WITH: String ends with value

Results

nametyperequiredconstraintsdescription
showConfirmationPagebooleanyesWhether to display a confirmation page after selection
tableModestringyesenum: DEFAULT, CUSTOMTable display mode: default shows all fields, custom shows only specified fields
fieldsarrayyesitems: DataSearchResultsFieldFields to display in results table (required when tableMode is CUSTOM)

Table Modes

  • DEFAULT: Display all available fields from the dataset
  • CUSTOM: Display only the fields specified in fields array

Results Field

nametyperequiredconstraintsdescription
fieldIdstringyesnullable: trueField identifier from dataset
customLabelstringyesDisplay label for the field in results table

Minimal Example (JSON)

{
  "datasets": [
    {
      "datasetId": "contacts_db",
      "setup": {
        "required": true,
        "selectionMode": "AUTOMATIC",
        "primarySearchCriteria": {
          "sortFieldId": "last_name",
          "sortDirection": "ASCENDING",
          "joinLogic": "AND",
          "filters": []
        },
        "linkedEntitiesFilters": {}
      },
      "results": {
        "showConfirmationPage": false,
        "tableMode": "DEFAULT",
        "fields": []
      }
    }
  ]
}

Full Example (JSON)

{
  "datasets": [
    {
      "datasetId": "customer_records",
      "setup": {
        "required": true,
        "selectionMode": "MANUAL",
        "primarySearchCriteria": {
          "sortFieldId": "last_name",
          "sortDirection": "ASCENDING",
          "joinLogic": "AND",
          "filters": [
            {
              "fieldId": "email",
              "operator": "EQUALS",
              "value": "{{`form`.`email`}}"
            },
            {
              "fieldId": "status",
              "operator": "EQUALS",
              "value": "active"
            },
            {
              "fieldId": "created_date",
              "operator": "GREATER_THAN_OR_EQUALS",
              "value": "2024-01-01"
            }
          ]
        },
        "linkedEntitiesFilters": {
          "orders": {
            "sortFieldId": "order_date",
            "sortDirection": "DESCENDING",
            "joinLogic": "OR",
            "filters": [
              {
                "fieldId": "status",
                "operator": "NOT_EQUALS",
                "value": "cancelled"
              },
              {
                "fieldId": "total_amount",
                "operator": "GREATER_THAN",
                "value": "100"
              }
            ]
          }
        }
      },
      "results": {
        "showConfirmationPage": true,
        "tableMode": "CUSTOM",
        "fields": [
          {
            "fieldId": "customer_id",
            "customLabel": "Customer ID"
          },
          {
            "fieldId": "first_name",
            "customLabel": "First Name"
          },
          {
            "fieldId": "last_name",
            "customLabel": "Last Name"
          },
          {
            "fieldId": "email",
            "customLabel": "Email Address"
          },
          {
            "fieldId": "phone",
            "customLabel": "Phone Number"
          }
        ]
      }
    }
  ]
}

TypeScript Example

import {
  dataSearchStepConfig,
  type DataSearchStepConfig,
} from '@odin/workflows-schema';

const searchStep: DataSearchStepConfig = {
  datasets: [
    {
      datasetId: 'product_catalog',
      setup: {
        required: false,
        selectionMode: 'MANUAL',
        primarySearchCriteria: {
          sortFieldId: 'product_name',
          sortDirection: 'ASCENDING',
          joinLogic: 'AND',
          filters: [
            {
              fieldId: 'category',
              operator: 'EQUALS',
              value: '{{`form`.`category`}}',
            },
            {
              fieldId: 'price',
              operator: 'LESS_THAN_OR_EQUALS',
              value: '{{`form`.`max_price`}}',
            },
            {
              fieldId: 'product_name',
              operator: 'CONTAINS',
              value: '{{`form`.`search_term`}}',
            },
          ],
        },
        linkedEntitiesFilters: {
          inventory: {
            sortFieldId: 'warehouse_id',
            sortDirection: 'ASCENDING',
            joinLogic: 'AND',
            filters: [
              {
                fieldId: 'quantity',
                operator: 'GREATER_THAN',
                value: '0',
              },
            ],
          },
        },
      },
      results: {
        showConfirmationPage: true,
        tableMode: 'CUSTOM',
        fields: [
          {
            fieldId: 'product_id',
            customLabel: 'Product ID',
          },
          {
            fieldId: 'product_name',
            customLabel: 'Product Name',
          },
          {
            fieldId: 'price',
            customLabel: 'Price',
          },
          {
            fieldId: 'in_stock',
            customLabel: 'In Stock',
          },
        ],
      },
    },
  ],
};

// Validate the configuration
const result = dataSearchStepConfig.safeParse(searchStep);
if (result.success) {
  console.log('Valid data search configuration');
} else {
  console.error('Validation errors:', result.error);
}