Skip to main content
Every database comes with a set of built-in functions. For example, FalkorDB functions include:
  • abs - computes the absolute value of a number
  • pow - computes v^x
  • trim - removes leading and trailing spaces.
These functions are built into the database and are part of its source code. Introducing a new function (for example, UpperCaseOdd) is not always trivial. The function needs to be usable to a wide audience for it to be considered. In the past, FalkorDB has rejected requests for adding new functions when these were too specific and did not add significant value for most users. However, with the support of UDFs, everyone can extend FalkorDB’s functionality with their own set of functions. The following sections introduce UDFs and explain how to manage and use them within FalkorDB.

Practical Example

To introduce UDFs, review the following complete example, which loads a new UDF library called “StringUtils” that includes a single function called “UpperCaseOdd”. Once loaded, the script puts the function to use.

Commands Specification

The FalkorDB-PY Python client provides convenient access to UDF functionality, but FalkorDB also exposes this functionality via a set of GRAPH.UDF <sub_cmd> commands.

GRAPH.UDF LOAD [REPLACE] <Lib> <script>

To add a UDF, call GRAPH.UDF LOAD followed by an optional REPLACE keyword. When specified, the REPLACE keyword replaces an already registered UDF library. The command then takes two arguments: the library name and the library script (written in JavaScript). A UDF library can expose multiple UDFs. The following example shows a script that includes both non-exposed utility functions and a number of callable functions:
For each UDF script, FalkorDB exposes the falkor object, through which you register UDFs. To register a function, call falkor.register and provide the name you wish to expose your function under, followed by either an anonymous function or the actual function. For example:
Once loaded your functions are available as if they were built-in functions and can be invoked in the same way. For example:

GRAPH.UDF LIST [Lib] [WITHCODE]

To list loaded UDF libraries you can either use the FalkorDB-PY udf_list function or invoke the GRAPH.UDF LIST command via a direct connection to the DB. The command takes two optional arguments:
  • Lib: list only a specific library.
  • WITHCODE: to include the library source code as part of the output.
For example: Calling the command: GRAPH.UDF LIST WITHCODE will generate the following output:

GRAPH.UDF DELETE <library>

To remove a UDF library use either the udf_delete FalkorDB-PY function, or send a GRAPH.UDF DELETE <library> command via a direct connection to the database. For example:

GRAPH.UDF FLUSH

Similar to delete GRAPH.UDF FLUSH removes all UDF libraries from the database.

Datatypes

Any datatype available in FalkorDB is accessible within UDFs, these include: Scalar, Node, Edge & Path objects.

Node

In a UDF, a node object exposes its ID, labels and attributes via the corresponding properties:
  • id - node internal ID
  • labels - node’s labels
  • attributes - node’s attributes
For example:
You can also collect a node’s neighbors by calling the node’s getNeighbors function. The getNeighbors function accepts an optional config map:

Edge

In a UDF, an edge object exposes its ID, type, source, target and attributes via the corresponding properties:
  • id - edge internal ID
  • type - edge’s relationship type
  • source - edge’s start node
  • target - edge’s end node
  • attributes - edge’s attributes
For example:

Path

In a UDF, a path object exposes its nodes, length and relationships via the corresponding properties:
  • nodes - path’s nodes
  • length - path’s length
  • relationships - path’s edges
For example:

Global objects

Breaking change (v4.16): The falkor.traverse() function has been removed. If your UDF scripts call falkor.traverse(...), migrate them to use graph.traverse(...) instead — the API accepts the same arguments. The graph object is the new unified interface for all graph-level operations.

Graph

UDFs have access to a global graph object which represents the current graph executing the UDF. The object exposes the following functions:

graph.traverse

Similar to the node’s getNeighbors function (see docs above), graph.traverse can perform multi-source traversal, which can be faster than performing multiple individual calls to getNeighbors.

graph.getNodeById

Description
Looks up and returns a single node by its internal graph ID. Returns null if no node with the given ID exists.
Syntax
Parameters
Return value
A Node object if the node exists, otherwise null.
Example

graph.iterateNodes

Description
Returns an iterator over all nodes in the graph that carry the specified label. The iterator is consumed with a standard for...of loop and yields Node objects one at a time. If no nodes with the given label exist, the iterator is empty and the loop body never executes.
Syntax
Parameters
Return value
An iterator of Node objects matching the given label.
Example

graph.iterateEdges

Description
Returns an iterator over all edges in the graph that have the specified relationship type. The iterator is consumed with a standard for...of loop and yields Edge objects one at a time. If no edges with the given relationship type exist, the iterator is empty and the loop body never executes.
Syntax
Parameters
Return value
An iterator of Edge objects matching the given relationship type.
Example

Falkor

The falkor global object represents the FalkorDB database and is used mostly to register UDFs. The object exposes two functions:
  • log - logs a message to the database stdout.
  • register - exposes a function to the database.

falkor.log

Description
Logs a message to the database stdout
Syntax
Parameters

falkor.register

Description
Register a function to the database
Syntax
Parameters
Example

Advanced examples

In this example, we’ll implement Jaccard similarity for nodes. Jaccard’s formula is: J(A,B) = |A ∩ B| / |A ∪ B| = |A ∩ B| / (|A| + |B| - |A ∩ B|) In simple terms, to compute Jaccard similarity for two nodes A and B, compute the number of shared neighbors between them and divide it by the total number of neighbors. If A and B have the same neighbors, their similarity value is 1. If they have no shared neighbors, their similarity value is 0. To start, define two UDFs (union and intersection) in a collection.js file:
With these functions defined, proceed to implement Jaccard similarity. Create similarity.js as follows:
Notice that jaccard uses both union and intersection from collection.js, and also collects A’s and B’s neighbors via a call to getNeighbors. The remaining step is to load these UDF libraries into FalkorDB and use them:
The scripts load our two UDF libraries, collection and similarity, construct a graph, and compute Jaccard similarity between Alice and every other node in the graph via the query:
Output:

Custom Traversals

In some situations where you want fine control over the way graph traversals are made, Cypher might not be flexible enough. Consider the following requirement: collect all reachable nodes from a given start node, where a neighbor node is added to the expanded path if its amount value is greater than the accumulated sum of amounts on the current path. The following UDF accomplishes this traversal. It performs a DFS and only expands to neighbors whose amount value is greater than the accumulated sum of amounts along the current path:
The remaining step is to load this UDF:

FLEX

FLEX (FalkorDB Library of Extensions) is FalkorDB’s open source community UDF package, available at github.com/FalkorDB/flex. It contains a variety of useful functionality, including:
  • String and set similarity metrics for fuzzy matching and comparison
  • Date and time manipulation, formatting, and parsing
  • Low-level bitwise operations on integers
Contributions to extend this library with additional functionality are welcome.

Limitations

Currently, UDFs are not allowed to modify the graph in any way. You cannot update graph entities within a UDF, nor can you add or delete entities.

Frequently Asked Questions

UDFs (User Defined Functions) are custom extensions written in JavaScript that let you add new functions to FalkorDB without modifying its source code. They are loaded via the udf_load command and called in Cypher queries.
No. Currently, UDFs are read-only — they cannot update, add, or delete graph entities. They can only compute and return values.
UDFs are called using the format LibraryName.FunctionName(args). For example: RETURN StringUtils.UpperCaseOdd('hello'). The library name is specified when loading the UDF.
UDFs are written in JavaScript. You define a function and register it using falkor.register('FunctionName', fn) to expose it to FalkorDB.