Skip to main content

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.

CASE SENSITIVITY

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.

attribute-to-attribute comparisons

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.

tip

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.

note

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.

warning

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.displayNamev.riskRating
SSL Certificate ExpiredHigh
SSL Certificate ExpiredHigh
SQL InjectionCritical
SQL InjectionCritical

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.displayNamev.riskRating
SSL Certificate ExpiredHigh
SQL InjectionCritical

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.

note

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

danger

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.

note

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.

    important

    Queries using OLAP must include an aggregation function, such as count(*), sum, min or max, 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.