Basic Keywords
This article introduces the basic keywords used in Brinqa Query Language (BQL), which form the main clauses of a query statement.
For additional syntax tips and advanced examples, please see the BQL Syntax and Style Guide and BQL Example Library.
BQL keywords are not case sensitive, but they appear in uppercase in documentation examples to help distinguish them from data model names, attributes, and values.
FIND
The FIND
clause searches for and retrieves records from a specific data model. FIND
must always be followed by the name of the data model you want to query.
FIND
is the starting point for every query. For example, the following query returns all vulnerabilities:
FIND Vulnerability
The following query returns all assets:
FIND Asset
While both queries are valid, they are broad. Without additional clauses, they may return too many results to be useful. To narrow your search, combine FIND
with clauses like WHERE, THAT, and WITH.
AS
The AS
clause assigns an alias to a data model so you can reference it throughout the query, typically in the WHERE
or RETURN
clause. Aliases improve readability when writing a query with multiple models and relationships.
For example, the following query assigns the alias f
to the Finding
data model and returns all critical-risk findings:
FIND Finding AS f WHERE f.riskRating = "Critical"
You can assign multiple aliases to different data models in a single query, as long as the two data models have a relationship. For example:
FIND Finding AS f
THAT HAS Asset AS a
WHERE f.severity = "Critical"
AND a.status = "Confirmed active"
The above query assigns f
to Finding and a
to Asset, then filters for critical findings on assets with a status of Confirmed active.
For additional information on viewing relationships between data models, see examine relationships between data models.
WHERE
Use the WHERE
clause to filter results by setting conditions on attributes. It helps narrow your query to return only the data that matches specific criteria. The attribute used in the WHERE
clause must exist on the target data model. You can check available attributes in the data model reference.
For example, the following query returns all users whose first name starts with "W"
:
FIND User AS u WHERE u.firstName STARTS WITH "W"
The firstName
attribute exists on the User data model, so the query runs successfully.
The following query returns all active findings with a medium severity level:
FIND Finding AS f WHERE f.status = "Confirmed active"
AND f.severity = "Medium"
Both the status
and severity
attribute exist on the Finding data model, so the query runs successfully.
To compare one attribute against another within the same data model, use the EQUALS TO ATTRIBUTE
operator instead of =
.
For example, the following query retrieves assets where the name
and ip
attributes have the same value:
FIND Asset AS a WHERE a.name EQUALS TO ATTRIBUTE a.ip
For additional information, see the Attribute operators.
THAT
Use the THAT
clause to traverse relationships between two data models. It enables your query to move from one model to another based on how they are related. THAT
must be followed by a relationship verb such as BELONGS
, HAS
, IS
, RELATES
, or SUPPORTS
. For additional information, see query for relationships in BQL.
In BQL, prepositions such as IN
, ON
, AT
, TO
, or BY
can be used after relationship keywords for fluidity, but they are ignored in terms of query processing. Thus, RELATES TO
and RELATES
are functionally identical.
Relationship verbs are not case sensitive. You can use them to reference any relationship between two data models. For example, the following query returns all hosts with associated vulnerabilities:
FIND Host AS h THAT HAS Vulnerability AS v
You can extend this with a WHERE
clause to filter the related model. The following query returns all hosts with critical vulnerabilities:
FIND Host AS h
THAT HAS Vulnerability AS v
WHERE v.severity = "Critical"
Relationship direction
Relationship verbs in BQL are bidirectional. This means both of the following queries are valid and return equivalent results:
FIND Asset AS a THAT HAS Vulnerability AS v
FIND Vulnerability AS v THAT HAS Asset AS a
Optional prepositions
BQL supports optional prepositions (TO
, IN
, BY
, etc.) after a relationship verb for natural language flow, but they are ignored in terms of query processing. For example:
FIND Vulnerability AS v
THAT RELATES TO VulnerabilityDefinition AS v2
Is functionally identical to:
FIND Vulnerability AS v
THAT RELATES VulnerabilityDefinition AS v2
Generic vs. specific relationships
Use RELATES
(or RELATES TO
) when you want to match any type of relationship between two data models. Use a specific verb like IS
, HAS
, or BELONGS
when you want to target a known relationship type.
For example, the following query returns any relationship between vulnerabilities and their definitions:
FIND Vulnerability AS v
THAT RELATES TO VulnerabilityDefinition AS v2
Whereas the following query only returns results where a defined IS
relationship exists between the two:
FIND Vulnerability AS v
THAT IS VulnerabilityDefinition AS v2
RETURN
Use the RETURN
clause to specify which values to include in the query results. This helps focus your output on relevant attributes and reduce unnecessary data.
You can only use RETURN
in reports, automations, and the Explorer chart mode. It is ignored in List views for assets, findings, or tickets. Additionally, you can only return the id
attribute in automations.
For example, when used in a report, the following query returns a number of unique vulnerabilities:
FIND Vulnerability AS v RETURN DISTINCT count(*)
This query is useful in reports when you need a de-duplicated count of vulnerabilities. By using DISTINCT count(*)
, you ensure that each vulnerability is only counted once, giving you an accurate count.
When using the RETURN
clause in automations, make sure to return only the id
attribute to avoid your automation failing. If your query involves one-to-many relationships, you can get duplicated records unless you add RETURN DISTINCT <alias>.id
to the end of the query.
For example, the following query can be used in automation to get a list of unique user IDs and their associated remediation owner IDs:
FIND User AS u THAT OWNS RemediationOwner AS ro THAT OWNS_REMEDIATION Finding AS f WHERE f.severity = "High" RETURN DISTINCT u.id, ro.id
In the above query, User
and RemediationOwner
have a one-to-many relationship. By returning DISTINCT u.id
, you ensure that only unique user IDs are returned, preventing duplicates.
DISTINCT
BQL queries may sometimes return duplicate rows when the data involves multiple paths of traversal between related models. This can happen even when the returned values appear identical.
To avoid this, you can use the DISTINCT
keyword with the RETURN
clause to ensure that only unique results are included in the final output.
You can only use DISTINCT
in areas that support the RETURN
clause: reports, automations, and Explorer chart mode. It is not supported in standard list views for assets, findings, or tickets.
Consider the following query, which returns vulnerabilities and their risk ratings based on their associated vulnerability definitions:
FIND Vulnerability AS v
THAT IS VulnerabilityDefinition AS v2
RETURN v.displayName, v.riskRating
Because a single vulnerability may have multiple associated vulnerability definitions, the above query can return duplicate rows even if the display name and risk rating appear the same.
Table 1: Query results without DISTINCT
v.displayName | v.riskRating |
---|---|
SSL Certificate Expired | High |
SSL Certificate Expired | High |
SQL Injection | Critical |
SQL Injection | Critical |
You can modify the query to add DISTINCT
to the RETURN
clause to remove any duplicates:
FIND Vulnerability AS v
THAT IS VulnerabilityDefinition AS v2
RETURN DISTINCT v.displayName, v.riskRating
The above query returns only the unique rows.
Table 2: Query results with DISTINCT
v.displayName | v.riskRating |
---|---|
SSL Certificate Expired | High |
SQL Injection | Critical |
WITH
The WITH
clause allows parts of the query statement to be tethered together, connecting the results from one to be used as starting points or criteria in the next. For example, the following query returns hosts with vulnerabilities in ascending order:
FIND Vulnerability AS v
THAT HAS Host AS h
WITH v, h.displayName AS order
ORDER BY order ASC
UNWIND
The UNWIND
clause is used in reports to break down a multi-valued attribute into separate rows, with each element in the collection represented as its own row in the query results. This allows you to work with individual values from a collection attribute more effectively.
You can only use UNWIND
in the report builder, specifically when using the advanced mode to write BQL queries for reports. If you do not add the UNDWIND
keyword in your query, the report builder automatically includes it when you select multi-valued attributes as dimensions.
For example, suppose you are building a report that lists hosts and their associated IP addresses. The UNWIND
keyword processes the ipAddresses
attribute, which stores multiple IPs for a single host, and returns each IP address as a separate row:
FIND Host AS h UNWIND h.ipAddresses AS Ips RETURN h.name, Ips
// Results:
h.name Ips
Host 1 127.0.0.1
Host 1 127.0.0.2
In the above query, the UNWIND
keyword breaks down the ipAddresses
collection into separate rows and each IP address is returned as an individual row.
USING
USING
is intended primarily for debugging by Brinqa Solution Engineers and is not recommended for daily, regular use. Improper usage can severely degrade system performance and lead to database crashes and restarts. If you have questions about the USING
keyword or its usage, please contact your Brinqa Support team for assistance.
The USING
keyword was introduced in Brinqa Platform version 11.30.
The USING
clause enables you to specify the database you want to query against, providing control over whether data is retrieved from Online Transaction Processing (OLTP) or Online Analytical Processing (OLAP):
-
OLTP: The primary data store that ingests and processes data through orchestration. This infrastructure supports on-demand queries and populates List views throughout the Brinqa Platform with data.
-
OLAP: Designed for delivering calculated datasets at speed and scale. The platform takes a complete snapshot of the data from OLTP, performs necessary calculations, and stores the results for use in analytics and reports. Since OLAP data is based on snapshots, it may not always reflect the most up-to-date data compared to OLTP.
importantQueries using
OLAP
must include an aggregation function, such ascount(*)
,sum
,min
ormax
, in order to execute successfully.
For instance, the following query can be used in a report to retrieve critical findings solely from OLAP:
USING OLAP FIND Finding AS f
RETURN DISTINCT f.riskRating AS "Risk rating", count(*)
AS Count ORDER BY "Risk rating" DESC LIMIT 10
Alternatively, the following query retrieves critical findings solely from OLTP:
USING OLTP FIND Finding AS f
RETURN DISTINCT f.riskRating AS "Risk rating", count(*)
AS Count ORDER BY "Risk rating" DESC LIMIT 10
The following query uses OLTP to retrieve person records, and can be used in an automation to create new Brinqa user accounts from people records:
USING OLTP FIND Person AS p WHERE p.firstName Contains
USING limitations
In addition to the syntax, some things to note about USING
:
-
Explorer:
USING OLAP
does not work in the Explorer, including both the table and graph views. However,USING OLTP
works in both views. -
Automations:
USING OLAP
shows an error when testing a query when you create an Automation, but it works when the automation runs. -
List views:
USING
is ignored in all other list views, including Assets, Findings, and Tickets. -
Reports: When creating reports, indicators, or visualizations, you can use
USING
in the advanced mode to formulate your query. However, the query is not saved and is ignored when the report loads.For example, if you want to verify how a report will look when pulling from the most recent dataset in OLTP instead of OLAP, you can test your query as follows:
USING OLTP FIND Asset AS a WHERE a.status = "Confirmed active"
Even though
USING
queries in reports cannot be saved and are ignored when the report loads, this can still be useful for testing and debugging to ensure the expected results.