Functions can be used to write complex Search Around functions, starting from one or more objects, and returning a graph of results. These functions can be executed from the Search Around toolbar menu, the right click menu, or when creating a graph using URL parameters. Each function must have exactly one argument that is an Ontology object type or a list of Ontology objects, and the function must have the return type IGraphSearchAroundResultV1
, as detailed below.
When used through the toolbar or right click menus, functions may have additional arguments of type Integer
, Double
, Float
, string
, boolean
, Timestamp
or Date
. When running these Search Arounds, a form will be generated for the user to input those parameters.
Search Around functions are written in a TypeScript functions repository. For more information, see the Functions documentation.
A Search Around function must declare a return type of IGraphSearchAroundResultV1
or Promise<IGraphSearchAroundResultV1>
. Vertex will discover the Search Around function using the name and structure of its return type, so it must be declared exactly as follows:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
export interface IGraphSearchAroundResultV1 { directEdges?: IGraphSearchAroundResultDirectEdgeV1[]; intermediateEdges?: IGraphSearchAroundResultIntermediateEdgeV1[]; orphanObjectRids?: string[]; objectRidsToGroup?: string[][]; layout?: string; } export interface IGraphSearchAroundResultDirectEdgeV1 { sourceObjectRid: string; targetObjectRid: string; linkTypeRid?: string; label?: string; direction?: string; } export interface IGraphSearchAroundResultIntermediateEdgeV1 { sourceObjectRid: string; sourceToIntermediateLinkTypeRid?: string; intermediateObjectRid: string; intermediateToTargetLinkTypeRid?: string; targetObjectRid: string; label?: string; direction?: string; }
directEdges
will be represented on the graph as an edge directly between two objects. If this edge is based on a link, its linkTypeRid
as found in the Ontology can be supplied to show the link type's display name along this edge and make Vertex aware of the edge direction.intermediateEdges
allow you to create edges between two objects based on events or other intermediate objects. An intermediate edge will be represented as an edge between two objects, with the intermediate object grouped into the edge. If many intermediate edges are returned between the same two objects, all intermediate objects will be grouped onto a single edge. As with direct edges, if the relationship represented is based on a pair of links (one from the source object to intermediate object, and a second from the intermediate object to target object), these link type RIDs can be supplied.orphanObjectRids
allow you to return objects that don't have any links to other objects in your response. Any objects that take part in either an edge in directEdges
or intermediateEdges
do not need to be returned in here.objectRidsToGroup
allows you to group objects into a single node by returning an array of groups, where each group is an array of object RIDs.label
allows you to specify a custom label for the functional link generated between the source and target object.direction
allows you to alter the directionality of the functional link produced by your search around function. The provided value must be one of NONE
, FORWARD
, or REVERSE
. Defaults to FORWARD
if omitted. Links that appear due to the presence of a linkTypeRid
are not affected by direction
.layout
allows you to alter the layout which the resulting objects use when being added to the graph. The provided value must be one of auto
, auto-grid
, grid
, linear-row
, linear-column
, or circular
. Defaults to a hierarchy layout if omitted.The following example contains two Search Around functions.
The first function allFlights
returns all flights along a route, merged onto a single edge between the Airports. For example, when run on route "SAN -> FAT", it produces the following:
The second function destinations
allows the user to choose a distance and returns all airports within that number of flights from the initial airport. For example, when run on airport "[ADK] Adak + Adak Island, AK" with a distance of 2, it produces the following:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
import { Function, Integer, OntologyObject } from "@foundry/functions-api" import { ExampleDataAirport, ExampleDataRoute } from "@foundry/ontology-api"; export interface IGraphSearchAroundResultV1 { directEdges?: IGraphSearchAroundResultDirectEdgeV1[]; intermediateEdges?: IGraphSearchAroundResultIntermediateEdgeV1[]; orphanObjectRids?: string[]; objectRidsToGroup?: string[][]; } export interface IGraphSearchAroundResultDirectEdgeV1 { sourceObjectRid: string; targetObjectRid: string; linkTypeRid?: string; } export interface IGraphSearchAroundResultIntermediateEdgeV1 { sourceObjectRid: string; sourceToIntermediateLinkTypeRid?: string; intermediateObjectRid: string; intermediateToTargetLinkTypeRid?: string; targetObjectRid: string; } export class VertexSearchArounds { @Function() public async allFlights(routes: ExampleDataRoute[]): Promise<IGraphSearchAroundResultV1> { const flights = await Promise.all(routes.map(route => route.flights.allAsync()); const intermediateEdges: IGraphSearchAroundResultIntermediateEdgeV1[] = []; for (let i = 0; i < routes.length; i++) { const route = routes[i]; const flightBetweenOriginAndDestination = flights[i]; const sourceObjectRid = route.departingAirport.get().rid!; const targetObjectRid = route.arrivingAirport.get().rid!; for (const flight of flightBetweenOriginAndDestination) { intermediateEdges.push({ sourceObjectRid, intermediateObjectRid: flight.rid!, targetObjectRid, }); } } const result: IGraphSearchAroundResultV1 = { intermediateEdges, }; return result; } @Function() public async destinations(airport: ExampleDataAirport, distance: Integer): Promise<IGraphSearchAroundResultV1> { let currentDistance = 0; let currentAirports = [airport]; const directEdges: IGraphSearchAroundResultDirectEdgeV1[] = []; while (currentDistance < distance) { let nextAirports = new Set<ExampleDataAirport>(); const routesByAirport = await Promise.all(currentAirports.map(airport => airport.routes.allAsync())); const destinationsByAirport = await Promise.all( routesByAirport.map(routes => Promise.all(routes.map(route => route.arrivingAirport.getAsync())) ) ); for (let i = 0; i < currentAirports.length; i++) { const airport = currentAirports[i]; const destinations = destinationsByAirport[i]; for (const destination of destinations) { directEdges.push({ sourceObjectRid: airport.rid!, targetObjectRid: destination!.rid!, }); } nextAirports.add(destination!); } currentAirports = Array.from(nextAirports); currentDistance++; } return { directEdges }; } }