Sometimes, in calculations, we need to perform some complex operations, such as making decisions by looking into all child risks, returning the sum of `bodilyInjury`

premium across all child risks, or finding out how many child risks exist for a given risk.

In BriteCore, you can query risks in many different ways.

## bc.risk

The rater provides `bc.risk`

utility, which can be used to query information from either the risk currently being rated or all of its child risks.

### bc.risk.number

Returns the risk number and can be used to identify whether it’s a first risk, second risk, third risk, and so on.

`bc.risk.number`

### bc.risk.term_premium

Returns the term premium from current risk.

`bc.risk.term_premium`

### bc.risk.pro_rata_premium

Returns the pro-rata premium from current risk.

`bc.risk.pro_rata_premium`

### bc.risk.get({lookup}, {default: optional})

Query information from the current risk. An optional `default`

value can be provided, which, by default, returns `None`

when the query isn’t resolved.

`bc.risk.get('fields.someField')`

Returns the value of `someField`

but returns `None`

if the query isn’t resolved.

## bc.risk.{descendants-risks}

This is the most powerful feature of risk querying, giving you access to perform aggregated operations on descendants risks.

### bc.risk.descendants({depth})

Returns specific descendants risks of provided `depth`

, which is a number that tells BriteCore to grab risks from only that particular level.

Example:

**Risk Type** hierarchy:

```
- Policy
- Vehicle
- Driver
- Violation
```

Querying at the policy level based on the hierarchy above:

```
bc.risk.descendants(1) # Returns risks at first level so only `Vehicle` risks will be returned
bc.risk.descendants(2) # Returns risks at second level so only `Driver` risks will be returned
bc.risk.descendants(3) # Returns risks at third level so only `Violation` risks will be returned
```

### bc.risk.descendants_up_to({depth})

Returns descendants risks up to provided `depth`

, which is a number that tells BriteCore to grab risks up to only that particular level.

Example:

**Risk Type** hierarchy:

```
- Policy
- Vehicle
- Driver
- Violation
```

Querying at the policy level based on the hierarchy above:

```
bc.risk.descendants_up_to(1) # Returns risks up to first level so only `Vehicle` risks will be returned
bc.risk.descendants_up_to(2) # Returns risks up to second level so `Vehicle` and `Driver` risks will be returned
bc.risk.descendants_up_to(3) # Returns risks up to third level so `Vehicle`, `Driver` and `Violation` risks will be returned
```

### bc.risk.all_descendants

Returns all descendants risks.

Example:

**Risk Type** hierarchy:

```
- Policy
- Vehicle
- Driver
- Violation
```

Querying at the policy level based on the hierarchy above:

`bc.risk.all_descendants`

Note:The query above will return all descendants risks:`Vehicle`

,`Driver`

and`Violation`

.

### bc.risk.children

Convenience method to get specific descendants risks of the first level, which is similar to `bc.risk.descendants(1)`

.

### bc.risk.grandchildren

Convenience method to get specific descendants risks of the second level, which is similar to `bc.risk.descendants(2)`

.

### bc.risk.great_grandchildren

Convenience method to get specific descendants risks of the third level, which is similar to `bc.risk.descendants(3)`

.

## Aggregated Operations

Aggregated operations can be performed on descendants risks.

All of the examples hereon can be used with the following:

`bc.risk.descendants({depth})`

`bc.risk.descendants_up_to({depth})`

`bc.risk.all_descendants`

`bc.risk.children`

`bc.risk.grandchildren`

`bc.risk.great_grandchildren`

Note:This isn’t limited to`bc.risk.children`

. For simplicity, we will use only`bc.risk.children`

for aggregation in examples hereon.

### Lookups

The aggregated operations are based on a `lookup`

expression used to define which field to aggregate.

#### Supported lookups

The example aggregation operation is `sum`

, and it can be any supported aggregation operation defined in the following subsections.

**bc.items**bc.risk.children.sum(bc.items.bodilyInjury.premium.term.value)

**bc.fields**bc.risk.children.sum(bc.fields.some_field)

**bc.premium**bc.risk.children.sum(bc.premium.term.value)

**bc.calculations**bc.risk.children.sum(bc.calculations.some_calculation)

**bc.rate_tables**bc.risk.children.sum(bc.rate_tables.some_rate_table)

### bc.risk.children.min({lookup})

Returns the minimum value from all child risks for a given `lookup`

.

`bc.risk.children.min(bc.items.bodilyInjury.premium.term.value)`

Returns the minimum `bodilyInjury`

premium across all child risks. So, if `bodilyInjury.premium.term.value`

(child risk 1) resolved to 1.0 and `bodilyInjury.premium.term.value`

(child risk 2) resolved to 2.0, then it will return `1.0`

.

Note:If there aren’t any child risks or the query isn’t resolved, then`min`

will return`None`

.

### bc.risk.children.max({lookup})

Returns the maximum value from all child risks for a given `lookup`

.

`bc.risk.children.max(bc.items.bodilyInjury.premium.term.value)`

Returns the minimum `bodilyInjury`

premium across all child risks. So, if `bodilyInjury.premium.term.value`

(child risk 1) resolved to 1.0 and `bodilyInjury.premium.term.value`

(child risk 2) resolved to 2.0, then it will return `2.0`

.

Note:If there aren’t any child risks or the query isn’t resolved, then`max`

will return`None`

.

### bc.risk.children.sum({lookup})

Returns the sum of all resolved values from all child risks for a given `lookup`

.

`bc.risk.children.sum(bc.items.bodilyInjury.premium.term.value)`

Returns the minimum `bodilyInjury`

premium across all child risks. So, if `bodilyInjury.premium.term.value`

(child risk 1) resolved to 1.0 and `bodilyInjury.premium.term.value`

(child risk 2) resolved to 2.0, then it will return `3.0`

.

### bc.risk.children.avg({lookup})

Returns the average of all resolved values from all child risks for a given `lookup`

.

`bc.risk.children.avg(bc.items.bodilyInjury.premium.term.value)`

Returns the minimum `bodilyInjury`

premium across all child risks. So, if `bodilyInjury.premium.term.value`

(child risk 1) resolved to 100.0 and `bodilyInjury.premium.term.value`

(child risk 2) resolved to 300.0, then it will return `200.0`

.

### bc.risk.children.count({lookup: optional})

Returns the count of all child risks. Optionally, you can pass `lookup`

, which checks its existence.

`bc.risk.children.count()`

If a risk has two sub-child risks, then the answer will be `2`

.

`bc.risk.children.count(bc.items.bodilyInjury)`

If a risk has two sub-child risks but only one of them has `bodilyInjury`

, then the answer will be `1`

.

### bc.risk.children.exists({lookup})

If the provided `lookup`

successfully resolved in any child risks, then it returns `True`

or `False`

.

`bc.risk.children.exists(bc.items.bodilyInjury)`

If any of the child risks has `bodilyInjury`

coverage enabled, then it returns `True`

; otherwise, it will return `False`

.

### bc.risk.children.get({lookup}, {default: optional})

Returns the value of a given `lookup`

.

Note:This operation should be accessed only after filtering all child risks to the point only one risk is found.

If there are multiple risks that meet the criteria, this operation will fail. You can provide an optional `default`

value, which, by default, returns `None`

if the query isn’t resolved.

`bc.risk.children.filter(type__name='drivers').get(bc.fields.goodStudent)`

The above returns the value of the `goodStudent`

field for the `drivers`

risk type, but if the query isn’t resolved, it returns `None`

.

## Children operations

### bc.risk.children.order_by({lookup1}, {lookup2}, …)

Sorts the child risks based on fields defined by one or more `lookups`

. By default, the results are sorted in ascending order.

Note:To sort the results in descending order, add the`-`

sign to the corresponding`lookup`

as a prefix.

`bc.risk.children.order_by(bc.items.bodilyInjury.premium.term.value)`

Returns the child risks and orders them by their `bodilyInjury`

coverage term premium, starting with the smallest.

`bc.risk.children.order_by(-bc.items.bodilyInjury.premium.term.value)`

Returns the child risks and orders them by their `bodilyInjury`

coverage term premium, starting with the largest.

`bc.risk.children.order_by(-bc.items.bodilyInjury.premium.term.value, bc.calculations.driverFactor)`

Returns the child risks:

- First, in descending order by their
`bodilyInjury`

coverage term premium. - Next, in ascending order by their
`driverFactor`

.

### bc.risk.children.limit({count})

Return a subset of the child risks, which is limited to the number defined by `count`

.

`bc.risk.children.limit(2)`

Returns only the first two child risks. If the original set is empty, an empty set is returned. If the original set contains only one child, then this child is returned.

### bc.risk.children.get_values({lookup})

Finds value for a given `lookup`

in all child risk states.

`bc.risk.children.get_values(bc.fields.name)`

Returns a list with the value of the `name`

field for all the child risks. If a child doesn’t have the `name`

field, nothing is added to the list for that child.

## Filtering

To filter before calling on aggregated operations:

`bc.risk.children.filter(*args, **kwargs)`

This filters child risks using the provided lookup parameters. Lookup parameters can be passed as:

**Keyword filtering:**Keyword arguments of the`fields__lookuptype=value`

type where`lookuptype`

specifies the filtering operation.`bc.risk.children.filter(number__gt=2)`

The above filter will match all child risks where the number field is greater than 2.

Each lookup is treated as a conditional clause. If multiple lookups are provided, then they are combined using the logical

`and`

operator.For nested fields, use a double underscore.

`bc.risk.children.filter(fields__mileage__lt=1000) -> will match all child risks where the mileage is less than 1000 bc.risk.children.filter(calculations__driverFactor=2.0) -> will match all child risks where the driverFactor calculation is 2.0 bc.risk.children.filter(rate_tables__bodilyInjuryBaseRateTable=100) -> will match all child risks where the bodilyInjuryBaseRateTable rate table is 100 bc.risk.children.filter(items__bodilyInjury__premium__term__value=2.0) -> will match all child risks where the bodilyInjury item's term premium is 2.0`

**Positional filtering:**Positional arguments of the`.filter(Q(...))`

type, which can be used to build conditional clauses that need to be either combined using logical`or`

or negated using`not`

.`bc.risk.children.filter(Q(number=1) | Q(number=2))`

The above query will filter only the child risk states where the number is either 1 or 2.

### Supported lookup types

The following are supported `lookup`

types:

**exact**exact equality (default)**neq**inequality**contains**containment**icontains**insensitive containment**in**membership**startswith**string startswith**istartswith**insensitive startswith**endswith**string endswith**iendswith**insensitive endswith**gt**greater than**gte**greater than or equal to**lt**less than**lte**less than or equal to**regex**regular expression search**filter**nested filter

Examples:

`bc.risk.children.filter(type__name='vehicles').min(bc.items.bodilyInjury.premium.term.value)`

– Returns minimum`bodilyInjury`

premium across all child`Vehicle`

risks.`bc.risk.children.filter(type__name__in=['vehicles', 'trailers']).min(bc.items.bodilyInjury.premium.term.value)`

– Returns minimum`bodilyInjury`

premium across all child`Vehicle`

or`Trailer`

risks.`bc.risk.children.filter(type__name='vehicles').min(bc.calculations.driverFactor)`

– Returns the minimum`driverFactor`

calculation result across all child`Vehicle`

risks.`bc.risk.children.filter(type__name='vehicles').min(bc.rate_tables.propertyDamageLimitFactorTable)`

– Returns the minimum`propertyDamageLimitFactorTable`

rate table result across all child`Vehicle`

risks`bc.risk.children.filter(type__name='vehicles').filter(fields__mileage__gte=1000).avg(bc.fields.mileage)`

– Returns the average`mileage`

across all`Vehicle`

risks whose`mileage`

is greater than or equal to 1000.`bc.risk.children.filter(type__name='vehicles').filter(~Q(fields__ratingTier__in=['ratingTier_standard', 'ratingTier_preferred']).count()`

– Returns the total count of all the`Vehicle`

risks whose`ratingTier`

is not`Standard`

or`Preferred`

.

### Gotchas!

Be aware of the following gotchas:

- Filtering should always come before aggregation operations (
`min`

,`max`

,`sum`

, or`count`

). - Filtering shouldn’t yield 0 results when using on following aggregated operations
`min`

,`max`

or`sum`

.

### Shorthand methods for filtering

The following is a shorthand method you can use as an alternative for `bc.risk.children.filter(type__name='vehicles')`

:

`bc.risk.{risk_type_name}`

Usage:

```
bc.risk.vehicles.count()
bc.risk.vehicles.min(bc.items.bodilyInjury.premium.term.value)
```

Note:If no risks have been added to the quote for the referenced risk type, the`min`

and`max`

will return`None`

.