You can use a NQE Decorator to add additional contextual data to your search results.
When adding a Decorator, you choose an Entity type. Depending on the type of Decorator you use, the contextual data will appear in a different area of your search results.

For example, if you choose to apply a decorator at the Device level, the additional data will be seen in the Device Card.
Here you can see the Basic Device Information query added as a Device Decorator:

In the following path search result, you can see two Decorators. There is a Path Decorator that calculates the Min and Max MTU along the entire path, as well as a Path Interface Decorator that displays the Link Speed. (The user must click on interface ge-0/0/3 in the Details card to see the Interface Decorator).

The NQE query structure required for a Decorator depends on the Decorator type.
For the Device Basic Info Decorator above, the standard Device Basic Info NQE query is used (/Forward Library/Devices/Device Basic Info)
/**
* @intent Basic information about Network Devices
*/
formatStatus(deviceSnapshotResult) =
when deviceSnapshotResult is
collectionFailed(collectionError) ->
"Collecting - " +
replace(toString(collectionError), "DeviceCollectionError.", "");
completed -> "Completed";
processingFailed(processingError) ->
"Processing - " +
replace(toString(processingError), "DeviceProcessingError.", "");
foreach device in network.devices
let platform = device.platform
let snapshotInfo = device.snapshotInfo
select {
Name: device.name,
Location: device.locationName,
Tags: device.tagNames,
Vendor: platform.vendor,
Model: platform.model,
"Interface Count": length(device.interfaces),
OS: platform.os,
"OS Version": platform.osVersion,
"Collection IP": snapshotInfo.collectionIp,
"Management IP(s)": platform.managementIps,
Status: formatStatus(device.snapshotInfo.result),
Type: platform.deviceType
}
Notice that the output of this NQE query is a table of devices.

When creating the Decorator, you choose "Name" for Device name column under Join columns. This tells the platform to look for the Device name in the Name column of the NQE query output, and display the rest of the data in that row in the Device Decorator.

To create a Path or Path Interface Decorator, you have to create a Parameterized NQE query that takes in a Path parameter. The NQE query then iterates over the hops in the path to perform its calculations. For example, by using foreach hop in path.hops
below:
/**
* @intent Gets the port speeds for interfaces on a path
*/
import "Interfaces/Interface Utilities";
getPortSpeed(deviceName, ifaceName) =
max(foreach i in getInterface(deviceName, ifaceName)
select i.ethernet.negotiatedPortSpeed);
// Returns entries for both sides of a path hop, so that a violation
// is shown on the egress out of an interface and on ingress into an
// interface.
@query
getPathPortSpeedInfo(path: Path) =
foreach hop in path.hops
let currentSpeed = getPortSpeed(hop.deviceName, hop.egressIfaceName)
where isPresent(currentSpeed) && isPresent(hop.nextDeviceName)
let nextSpeed = getPortSpeed(hop.nextDeviceName, hop.nextIfaceName)
where isPresent(nextSpeed)
let violation = currentSpeed != PortSpeed.SPEED_UNKNOWN &&
nextSpeed != PortSpeed.SPEED_UNKNOWN &&
nextSpeed != currentSpeed
let egressRecord = { hopIndex: hop.index,
direction: Direction.EGRESS,
Speed: formatPortSpeed(currentSpeed),
"Neighbor Speed": formatPortSpeed(nextSpeed),
violation
}
let ingressRecord = { hopIndex: hop.index + 1,
direction: Direction.INGRESS,
Speed: formatPortSpeed(nextSpeed),
"Neighbor Speed": formatPortSpeed(currentSpeed),
violation
}
foreach record in regressRecord, ingressRecord]
select record;
In the Path Interface Link Speed query (/Forward Library/Interfaces/Path Interface Link Speed), a table of interface speeds is created per hop. In this example, the Hop Index is associated with the hopIndex column to create the Path Interface Decorator.

In the Path MTU query (/Forward Library/Interfaces/Path MTU) the minimum and maximum MTU for the path are calculated.
Note the @query getPathMtuInfo(path: Path)
function. This function is used to convert this query into a Parameterized Query, which takes a Path as an argument.
/**
* @intent Gets the min and max MTUs for interfaces on a path
*/
getIface(ifaces, ifaceName) =
foreach iface in ifaces
where iface.name == ifaceName
select iface;
ifaceMtus(path) =
foreach hop in path.hops
foreach device in network.devices
where device.name == hop.deviceName
foreach iface in device.interfaces
foreach iface
in getIface(device.interfaces, hop.egressIfaceName) +
getIface(device.interfaces, hop.ingressIfaceName)
where isPresent(iface.mtu)
select iface.mtu;
@query
getPathMtuInfo(path: Path) =
foreach mtus in ifaceMtus(path)]
let minMtu = min(mtus)
let maxMtu = max(mtus)
select { "Min MTU": minMtu, "Max MTU": maxMtu, violation: minMtu != maxMtu };
When associating an NQE query with an Path Decorator, notice that there is no Join Columns field, because the query results are applied at the Path card level, and the Parameterized NQE query takes that Path as an argument.
