Querying

Forms Developer Guides Querying

Sonadier has a JSON-based format for querying form submissions, including nested conditions and queries through connections. This format can be passed to the REST API with URL parameters, or to a Scripting Query method to retrieve matching submissions.

Simple Conditions

If your query doesn't need or conditions or nesting, you can use a simple { field_name: "value" } format. This format will generate conditions like [{ field: "status", operator: "==", value: "Complete"}].

Form.new(permalink).submissions.query({ status: "Complete" }).then(function(submissions) {
  for (var i = 0; i < submissions.length; i++) {
    console.log(submissions[i].field("name"));
  }
});

Normal Conditions and Operators

The "real" format for conditions is an array of individual condition objects. Different field types support different operators, but the basic equality check uses ==.

[
  { field: "status", operator: "==", value: "Complete" },
  { field: "created", operator: ">", value: "yesterday" }
]

You can check for multiple values by setting the value to an array. This checks if any of the values match.

[
  { field: "permalink", operator: "==", value: [permalink1, permalink2] }
]

Nested Conditions, Groups, and Logical Operators

Conditions can be nested inside Groups, which can check their conditions using and (if all are true) or or (if any is true). Groups can be nested inside other groups to build more complex queries.

  • Define a group by setting the type key to "group".
  • Groups can have operator values, either and or or. It defaults to and if it's not set.
  • If negative key is true, the conditions will be reversed.

The query below fetches assignments which are due. The first group checks for any responses where the status is "Complete", or the due date has passed. The second group excludes responses created by the "teacher" account, or the due date was extended. Note the negative: true option reversing the second group's conditions.

[
  {
    type: "group",
    operator: "and",
    conditions: [
      { field: "status", operator: "==", "Complete" },
      { field: "due_date", operator: "<", "today" }
    ]
  },
  {
    type: "group",
    operator: "or",
    negative: true,
    conditions: [
      { field: "creator", operator: "==", value: "teacher" },
      { field: "due_date_extended", operator: "==", value: true }
    ]
  }
]

The first group's conditions could have been included directly in the top-level array, as it checks using and.

[
  { field: "status", operator: "==", "Complete" },
  { field: "due_date", operator: "<", "today" }
  {
    type: "group",
    operator: "or",
    negative: true,
    conditions: [
      { field: "creator", operator: "==", value: "teacher" },
      { field: "due_date_extended", operator: "==", value: true }
    ]
  }
]

Top-Level Groups

Behind the scenes, the top-level array is moved into an and group before evaluation, like the example below. You can pass your own top-level group object instead if you'd like to add extra options.

{
  type: "group", operator: "and", conditions: [..your conditions..]
}

Querying Through Connections

To check for responses with connections matching conditions, use the == or != operators, and pass Query JSON in the value. You can also use the % and !% operators to check if the connected permalinks or primary field values match strings.

The query below will return all responses connected to a response with a status field set to "Complete". The == operator checks if any connected responses match, while the != operator checks that all responses do not match.

{
  field: "connection",
  operator: "==",
  value: [
    { field: "status", operator: "==", value: "Complete" }
  ]
}

If you pass a String to the value field of an == or != condition, the query will look for a Report by that permalink, and evaluate whether the connected responses match it.

Parsing Query JSON

JSON Query objects can be returned by the Report REST API, or by certain custom script methods. If you need to read or write to these objects, some basic tips are included below.

Queries can be passed with several levels of strictness, starting with the "Simple Conditions" examples seen above. We convert all query inputs to a stricter form which is easier for code to deal with.

In the same way that groups have a type key set to "group", conditions have a type set to "condition". By convention, it's left out when writing queries directly, and it's implied by a missing type.

The simplest way to write queries is with the "Simple Condition" format. It leaves almost everything to implication, with an implied == operator.

{ creator: "teacher" }

The normal way to write the same query leaves less to implication.

[
  { field: "creator", operator: "==", value: "teacher" }
]

The strict query format, returned by the API, presents more consistent parameters for parsers. If you're using code to retrieve a Report or Table's query, it will be returned in this format.

{
  type: "group",
  operator: "and",
  negative: false,
  conditions: [
    {
      type: "condition",
      field: "creator",
      operator: "==",
      value: "teacher"
    }
  ]
}