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, eitherand
oror
. It defaults toand
if it's not set. - If
negative
key istrue
, 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"
}
]
}