Skip to main content

Teneo Query Language Cookbook

Lists​

List all values of a variable​

Use listUnique on the variable:

lu t.e.sv:s:userCountry : exists t.e.sv:s:userCountry

sv:s:userCountry is meant to be a string (s:) session variable (sv:) defined in the bot

List unique inputs to a flow​

Use listUnique combined with a constraint on the flow name or flow ID:

lu t.e.userInput : t.e.type=="request", t.e2.fname == "User says yes"

List user input words showing positive or negative trend​

Use the trend transformer and set the cut off values to the appropriate values (recommended values below):

lu t.e.userInputWords, tau, direction, p, z :
t.e.type == "request",
trend (max-p="0.05", min-tau="0.2") t.e.userInputWords as (tau, direction, p, z)
order by tau

The trend algorithm is based on the Mann-Kendall trend test, which is a specific implementation of the general Kendall Tau correlation test.

List variable values matching a pattern​

For this example, list country names starting with a capital vowel.

Use regular expression matching on the variable value:

lu t.e.sv:s:userCountry : t.e.sv:s:userCountry ~= ".[A|E|I|O|U].+"

sv:userCountry is meant to be a string (s:) session variable (sv:) defined in the bot.

A quotation mark may be part of a variable value, hence the leading dot in the regex above.

List flows immediately preceding safetynet​

Use listUnique and skip-to for controlling the order events:

lu t1.e.fname, t.e.fname :
t1.e.pathType=="raise-flow",
t1.e-{pathType=="raise-flow"}>t2.e,
t2.e.fname ~= ".*[s|S]afetynet.*"

List review reason meta-data values​

Use listUnique and regex constraint on the review reason variable:

lu t.e.md:REVIEW_REASON : t.e.md:REVIEW_REASON ~= ".+"

md:REVIEW_REASON is meant to be a metadata variable defined in the solution.

List review reason meta-data values with user inputs and flow names​

Use listUnique and regex constraint on the review reason variable, in combination with user input and flow name:

lu t.e1.userInput, t.e2.fname, t.e3.md:REVIEW_REASON :
t.e1.type=="request",
t.e1.userInput ~= ".+",
exists t.e2.fname,
t.e3.md:REVIEW_REASON ~= ".+"

md:REVIEW_REASON is meant to be a metadata variable defined in the solution.

List negative feedback comments accompanied by a negative rating​

Use listUnique with a constraint on the feedback rating variable:

lu t1.e.md:FEEDBACK_COMMENT, t2.e.md:FEEDBACK_RATING :
t1.e.md:FEEDBACK_COMMENT ~= ".+",
t2.e.md:FEEDBACK_RATING ~= "negative"

md:FEEDBACK, md:FEEDBACK_RATING, and md:FEEDBACK_COMMENT are meant to be metadata variables defined in the solution.

List user inputs matching a language object condition​

Use listUnique with the matches-condition transformer:

lu t.e.userInput :
t.e.type == "request",
t.e.userInput matches-condition (solution="en_tlr", condition = "%WHO.FW.LEX + %BE.VB.LEX")

The example above shows that the condition parameter accepts any valid combination of language objects and condition operators. However, the same condition could be rewritten using a single language object: “WHO_IS.PHR”. Note also that this query only works if a solution "en_tlr" has been associated with the log data.

List language objects matching user inputs​

This can be used to analyze how to improve conditions in the solution according to the matching LOBs.

Use listUnique with the matching-lobs transformer:

lu t.e.userInput, lob, used-words :
matching-lobs(solution="en_tlr") t.e.userInput as (lob, used-words)

Note that this query only works if a solution "en_tlr" has been associated with the log data.

List triggered flows per day from aggregated data​

Use listAll on the aggregated data:

la (a="test") triggeredFlowsIdPerDay

The example above assumes that an aggregator "test" has been created, with the property triggeredFlowsIdPerDay which contains the relevant flow IDs.

List words matching pattern irrespective of case​

In this case, list all user inputs containing "hello" irrespective of case.

Use listAll on userInputWords with the ~~ operator:

la t.e.userInputWords :
t.e.type == "request", t.e.userInputWords ~~ "hello"

List inputs going to a particular trigger​

Use listAll and specify the name of the trigger, combined with skip-constraints:

la t.e1.userInput, t.e2.vname :
t.e1.type=="request",
t.e2.vname=="Send SMS",
t.e1-{pathType=="flow-trigger"}>t.e2

The example is based on a solution that retrieves inputs going to the Send SMS trigger.

List answers after a particular trigger​

Use listAll and specify the name of the trigger, combined with skip-constraints:

la t.e1.vname, t.e2.answerText :
t.e1.pathType=="flow-trigger" ,
t.e1.vname=="Send SMS",
t.e1-{type=="response"}>t.e2

The example is based on a solution that retrieves inputs going to the Send SMS trigger.

Count and averages​

Count the number of dialogues​

Use countUnique or countAll on the session id:

cu s.id
ca s.id

Count user inputs​

Use countAll on the user input (use countUnique to get types rather than tokens):

ca t.e.userInput : t.e.type=="request"

Count number of values found in a variable​

Use countUnique in combination with a sub-query:

cu x.city :
x=@(lu t.e.sv:s:userCity as city : t.e.sv:s:userCity ~= "...+")

sv:userCountry is meant to be a string (s:) session variable (sv:) defined in the solution.

Count bot responses​

Use countAll on the output text (use countUnique to get types rather than tokens):

ca t.e.answerText :
t.e.type=="response",
exists t.e.answerText

Calculate mean transaction count for a time period​

Use the mean prefix in combination with a sub-query:

lu mean x.count as meanCount :
x=@(lu s.id, s.transactionCount as count : s.beginTime=="2015-03-11")

Calculate mean number of empty inputs for a time period​

Use the mean prefix in combination with a sub query:

lu mean x.count as meanEmptyCount :
x=@(d date, t.e.userInput :
t.e.type=="request",
t.e.userInput == "",
catd(model="date") s.beginTime as date,
s.beginTime == in {"2015-03-11".."2015-03-17"})

Calculate mean number of results for aggregated data​

Use listAll in combination with the mean prefix:

la (a="test") mean count, date

This example assumes that an aggregator "test" with the properties date and count has been created.

Frequency lists​

To create top N lists from the solutions, use limit, e.g. limit 10 for a top-10 list (when sorted in descending order).

Most frequent user inputs​

Use distribute and order by count, specify request events:

d t.e.userInput :
t.e.type=="request",
t.e.userInput ~= ".+"
order by count desc

Most triggered flows​

Use distribute and order by count, specify flow-trigger events:

d t.e.fname :
t.e.pathType=="flow-trigger"
order by count desc

Most frequent safetynet inputs​

Use distribute and order by count, combined search for request and flow-trigger events:

d t.e.userInput :
t.e.type=="request",
t.e.userInput ~= ".+",
t.e2.pathType == "flow-trigger",
t.e2.fname ~= ".*[s|S]afetynet.*"
order by count desc

Frequency of variable values​

Count the number of values of a variable and sort in decreasing order.

Use distribute and order by count, applied to variable:

d t.e.sv:s:userCountry :
exists t.e.sv:s:userCountry
order by count desc

sv:s:userCountry is meant to be a string (s:) session variable (sv:) defined in the solution.

The default value of the variable (such as "") is also listed. Use regex matching to require a longer string if "" is to be excluded.

Frequency of flows triggered by a specified input​

Count the number of flows that are triggered by a specific input and sort in decreasing order.

Use distribute and order by count, in combination with skip-to:

d t.e1.userInput, t.e2.fname :
t.e1.type=="request",
t.e1.userInput ~= ".*hungry.*",
t.e1-{pathType=="flow-trigger"}>t.e2
order by count desc

Returns frequency list of user inputs containing "hungry" and triggered flows.

Frequency of flow triggers​

Count the number of times flow triggers have been activated and sort in decreasing order.

Use distribute and order by count, specify flow-trigger events:

d t.e1.fname :
t.e1.pathType=="flow-trigger",
exists t.e1.fname
order by count desc

Frequency of sessions per specified time period​

Count the number of sessions per e.g. day or week and sort chronologically by date.

Use distribute and order by date asc:

d date :
catd(model="date") s.beginTime as date
order by date asc
d week :
catd(pattern="yyyy-'w'ww") s.beginTime as week
order by week asc

Frequency of sessions with an input triggering Safetynet by day​

Use distribute to count sessions, with a constraint on the flow name:

d date :
catd(model="date") s.beginTime as date,
t.e1.type=="request",
t.e2.fname~=".*[s|S]afetynet.*"

Frequency of triggered flow folders​

Count the number of times the flows from various folders have been triggered and sort in decreasing order.

Use distribute with folder:

d t.e.folder :
t.e.pathType=="flow-trigger",
t.e.folder ~= ".+"
order by count desc

Frequency of traversed Safetynet transitions​

Count the number of times the different transitions in the Safetynet flow(s) have been logged, and list the names and IDs of the transitions sorted in decreasing order.

Use distribute with the transition path type:

d t.e.vname, t.e.vid :
t.e.pathType=="transition",
t.e.vname ~= ".+",
t.e.fname ~= ".*[S|s]afetynet.*"
order by count desc

Frequency of review reason values​

Count the number of non-empty values of the review reason metadata variable, and sort in decreasing order.

Use distribute with a regex constraint on the review reason variable:

d t.e.md:REVIEW_REASON :
t.e.md:REVIEW_REASON ~= ".+"
order by count desc

md:REVIEW_REASON is meant to be a metadata variable defined in the solution.

Frequency of feedback rating​

Count the number of different feedback ratings, and sort in decreasing order.

Use distribute on the feedback rating variable:

d t.e.md:FEEDBACK_RATING :
t.e.md:FEEDBACK_RATING ~= ".+"
order by count desc

md:FEEDBACK_RATING is meant to be a metadata variable defined in the solution.

Frequency of inputs matching A OR B​

Count user inputs matching one of two or more possible values.

Use distribute in combination with set constraints to emulate a logical OR condition:

d t.e.userInput :
t.e.type == "request",
t.e.userInput ~= in {"A", "B"}