If we query a heavily used system to show us a list of all user inputs it ever received, the result will be more data than we can handle. We need to filter it down, to perhaps a relevant hour, or in which some specific event occurred during the conversation, etc. These filters we add are called constraints. Constraints are the way you can specify which session, transaction and event properties are relevant for your query. Not every query needs a constraint, only if you wish to add a layer of specificity. If you're exploring your data, you may first want to see what's there, and then refine the query with constraints to zoom in on what you need. Constraints are separated from the selection by a colon symbol (:) and can consist of multiple terms, all separated by commas.

In our example query the constraint part is t.e.userInput != "" :

la, t.e.userInput, t.e2.answerText:  t.e.userInput != "" limit 30

The command and selection part are saying: show me all the user input + bot response pairs, along with the session ID they belong to. The constraint however causes some question+answer pairs to be excluded from the report, those in which the user input was blank, e.g. the user hit enter. The constraint syntax allows us to specify conditions that must be met in order to include those particular properties in the selection. You can use standard logical operators for constraints as well as regular expressions.

Core constraint operators

TQL supports the eight basic constraint operators listed in the table below. The table shows a brief explanation of their function, an indication of whether or not they support regular expressions, what field types they apply to, and example event properties they can be applied to.

Operator Function Support regex Applies to Example event properties
== equals no strings, numeric, date userInput, index, beginTime
!= not equals no strings, numeric, date userInput, index, beginTime
~= matches yes strings userInput, folder, fname
!~ not matches yes strings userInput, folder, fname
~~ contains no analyzed text userInputWords, answerTextWords
!~~ not contains no analyzed text userInputWords, answerTextWords
exists x exists no any any
notexists x does not exist no any Any
>, <, >=, <= greater than x, less than x, greater or equal than x, less or equal than x no numeric, date transactionsCount, beginTime,

The exists and notexists operators are special in that they only take one argument (the event property to check) and return a match if it exists.

The contains operator ~~ can be used to perform case-insensitive queries of userInputWords and answerTextWords, by checking if a field contains or does not contain a word or word sequence. This is possible because these two fields are stored as analyzed text, which is lowercased, tokenized, and normalized before being stored as an array of tokens (words).

Advanced constraints

TQL offers two advanced possibilities you can use to construct especially precise queries: sub queries and skip constraints.

Sub queries

Sub queries allow you to nest a complete TQL query in a main query and access the results in the selection. This is useful, for example, in exploring aggregate results such as averages, etc. The schematic for for sub queries is:

x = @( TQL query )

This example shows our sample query adapted as a sub query. In the selection we display unique occurrences of the id we found:

lu result = @(la as id, t.e.userInput, t.e2.answerText:  t.e.userInput != "")

We explore sub queries more deeply on this how to page.

Skip constraints

With skip constraints you can finds pairs of events or transactions in which the end point is the first occurrence of a particular event or transaction after the starting point. The skip-to syntax specifies the order of precedence among transitions or events by setting out a starting point and an end point, where the start or end point has some property. The syntax (in pseudo-code) is schematically as follows:

start -{end point constraints}> end point
end point <{start point constraints}- start

The starting and end points can be transactions or events (not necessarily in the same transaction). The constraints enclosed by {} specify the constraints the start or end point must fulfil. The direction of the arrow specifies whether the constraint is skipping forward or backwards in the session.

We'll give you a closer view of the syntax as well as some use cases at our how to page on using skip constraints.

Was this page helpful?