Query Guide

Queries are handy when you want to extract a dataset from Rhythm, which might include data from multiple apps. Generally, this data is used to synchronize another system or to establish a cache that you manage. You could then access this data behind your own APIs. These kinds of queries are usually executed on a regular interval, such as every hour, and may define criteria to only return records that have been modified in that time.

info

Depending on the complexity of a query, it may take several seconds to complete. It is therefore queries are not recommended for use-cases where users will be waiting on the query to execute, such as displaying results on a webpage. In those cases, the recommended approach is to use the specific endpoints in the App References, or to run the query periodically and cache the results behind your own APIs.

Authentication

Since queries are not recommended for direct user interactions, they are usually executed by a script or other scheduled process. In these machine-to-machine scenarios, the client credentials authentication flow is required to generate your access token.

Please review the authentication quick start for more information and be sure to cache those tokens if you are going to execute more than one query per-day.

Overview

Start by deciding where to store your query. You can store the query as an asset in your program (static query), or retrieve it at execution time from the Rhythm API (dynamic query). Below we'll take a look at how those flows differ.

Query Types

A query is specific to a particular query type. A query type might be rolodex:contacts or events:functions. Different query types usually have different fields available for use in a query. This is why a query returning a set of fields may not be valid for a different query type.

Query UI

It is often helpful to use the Rhythm console UI to define your query. This makes it easy to find the query type and fields you are interested in, as well as to set the default criteria see (see Criteria section below).

Starting a Query

Once you have your query, you can POST it to the System API > Queries endpoint. In the URI of this POST, you can specify the query type, and the format for the results. Valid values include json, csv, excel, excelUnformatted, or xml. This POST will start your query and return you the query execution ID.

Performance

The format you choose for your results directly impacts the performance of the CONVERTING status of the query. Queries using csv or json perform the best.

Getting Query Results

You can use the query execution ID in the URI of the System API > Queries endpoint. The response will return information about the execution including its current status. Once the status is FINISHED, the response will also include a URL where you can retrieve the query results or metadata about the fields included in the results.

If the query status is not yet FINISHED, you can delay for a second or two, then retry the request to get the updated query status. Since this polling mechanism is common for long-running tasks on a REST API, there are many libraries available in major frameworks that will handle this for you. For JavaScript, we recommend using https://www.npmjs.com/package/async-retry with the following default configuration:

{
  retries: 10,
  factor: 1.25,
  minTimeout: 1000,
  maxTimeout: 3000,
}

Static Query

Storing your query definition as an asset in your program is useful when your program requires a particular result set. This puts you in full control of your query definition, which you can even version control.

Your codeAuth0System APIResults storageClient credentialsAccess tokenQuery definition + Access tokenQuery IDQuery ID + Access tokenQuery statusloop[Describe query]Response will include location ofresults when the query status isFINISHED.Request resultsResultsYour codeAuth0System APIResults storage

Dynamic Query

Retrieving the query at execution time is useful when you want to allow Rhythm console users to easily change the definition of the query in the future.

info

Rhythm uses this method for many of our standard integrations to allow different tenants to define the criteria and fields they are interested in.

The dynamic query flow is similar to the static query, however before the query is started, it is retrieved from the Platform API > Saved Queries endpoints. The query may be manipulated before starting it to ensure required fields or criteria are included.

Your codeAuth0Platform APISystem APIResults storageClient credentialsAccess tokenSaved query ID + Access tokenQuery definitionQuery definition + Access tokenQuery IDQuery ID + Access tokenQuery statusloop[Describe query]Response will include location ofresults when the query status isFINISHED.Request resultsResultsYour codeAuth0Platform APISystem APIResults storage

Criteria

Whether you are storing the query definition in your source code or retrieving it at runtime, it is often helpful to override the criteria before executing your query. You might do this to only retrieve records that have been modified since the last time the query was executed.

Every query has an optional criteria property which uses JSON Rules Engine syntax. Because this syntax is recursive, the criteria property only appears with the type object in the Reference: System documentation and samples.

If you are having trouble defining your criteria, we recommend using the Rhythm UI to build a query definition. You can use your browser's inspector to see how different options change the query definition. To get access to the Rhythm console, please contact support@rhythmsoftware.com

Query Criteria in the Browser Inspector

Alternatively, you can save your query, then retrieve it from the API using the Platform API > Saved Queries endpoints.

Grouping

The criteria object begins with a grouping. This can be an any group (OR) or an all group (AND). Both groups are arrays which contain the individual criteria objects to examine for this group. Every criteria object in this group can optionally define their own any or all arrays to support nested grouping.

Fact

Every criteria must specify a fact which refers to the table that contains the data to compare. fact values must correspond to a table_alias value from the query type being executed.

Operator

Every criteria must specify a operator to use in comparison. operator can be one of: equal, notEqual, containsString, regex, lessThan, lessThanInclusive, greaterThan, greaterThanInclusive, in, notIn, contains, doesNotContain, isBlank, isNotBlank

Path

Every criteria must specify a path identifying the field to compare. This value uses JSON path to locate the path. This might be a value like $.first_name.

Value

Every criteria must specify a value. How this value is compared to the field defined in fact and path is determined by the operator you select.

Examples

Criteria

You can combine multiple criteria such this example criteria object:

{
  "all": [
    {
      "any": [
        {
          "path": "$.first_name",
          "fact": "main",
          "value": "Tony",
          "operator": "notEqual"
        },
        {
          "path": "$.last_name",
          "fact": "main",
          "value": "Stark",
          "operator": "equal"
        }
      ]
    },
    {
      "path": "$.rolodex_contacts__company_name__c",
      "fact": "main",
      "value": false,
      "operator": "isNotBlank"
    }  
  ]
}

Query

The following is an example query definition for the rolodex:contacts query type. This JSON can be sent as the body of a POST to https://system.api.rhythmsoftware.com/queries/{tenantId}/start/rolodex%3Acontacts/json to start a new query:

{
  "output_fields": [
    {
      "name": "name"
    },
    {
      "name": "organization_name"
    },
    {
      "name": "email_address"
    },
    {
      "name": "preferred_address__city"
    },
    {
      "name": "preferred_address__state"
    },
    {
      "name": "rolodex_contacts__company_name__c",
      "label": "Company Name"
    },
    {
      "name": "rolodex_contacts__companyname__c",
      "label": "companyName"
    }
  ],
  "name": "Contacts with Organization and Company Name",
  "sort_fields": [
    {
      "name": "name"
    }
  ],
  "criteria": {
    "all": [
      {
        "path": "$.rolodex_contacts__company_name__c",
        "fact": "main",
        "value": false,
        "operator": "isNotBlank"
      }
    ]
  }
}