Working with RAI Notebooks

A short guide to working with RelationalAI notebooks.

RelationalAI notebooks are a great way to interact with the RKGMS database, visualize data, and develop your next data science project. If you’re familiar with Jupyter notebooks, cells in a RelationalAI notebook work in a somewhat similar way.

Since notebooks are designed to interact with the RGKMS database, however, there are some important differences, described here.

Working with Cells

RelationalAI notebooks use four different types of cells. When you open a new notebook, you’ll see one cell with a default type of Query.

To select a different cell type, use the pull-down menu at the top left of the cell.

To add a new cell, mouse over the area to the left of a cell and click one of the “+” icons. The “+” icon at the top left adds a cell before the current cell, while the “+” icon at the lower left adds a cell after the current cell. You can also use Ctrl-Enter to run a cell’s contents and create a new cell below the current cell.

To hide a cell, mouse over the area to the left of a cell and click the Toggle Folding (eye) icon.

To delete a cell, click the “X” icon in the top right of the cell.

Choosing a Cell Type

For each cell, you choose a cell type. These have different behaviors, and your choice of them depends on what you’re trying to achieve.

Cell TypeBehavior
QueryQuery values from the database, without making changes to the database.
InstallInstall definitions, entities, and logic into the database (see also the Installing Models guide). Definitions in these cells will be available to other cells in both the notebook and database.
UpdatePerform data updates that you do not want to run repeatedly, such as inserting and deleting tuples. You should generally use Update cells to manage EDB data.
MarkdownWrite explanatory text in Markdown.

Query Cells

When you run code in a Query cell, the code only affects the cell itself. That is, Query cells execute read-only transactions. Any definitions that you create here will not be available to other cells in the notebook.

As their name suggests, Query cells are especially useful for querying values out of the RKGMS database.

To use a simple example, if you know that the database has a relation called employee, you can run a query along the following lines to view data from employee.

query
employee

You can run more complex queries in Query cells as well:

query
def city_population = {
("New York, NY", 8804190);
("Los Angeles, CA", 3898747 );
("Cambridge, MA", 118403);
}

def big_cities(city) = city_population[city] > 10^6

def output:cities = big_cities
def output:city_pop = city_population

For queries with one or more definitions, the relation output is, by convention, the one whose data is displayed in the notebook.

To display more than one relation, we used the module syntax (i.e., output:cities) to give each output relation a name.

Note that the relations big_cities and city_population are defined only within this Query cell and can’t be accessed in any another cell.

To make city_population and big_cities available to other cells, you need to write them to the database as EDB relations, or put their definition in in an Install cell.

Considering that city_population is really data, from which other predicates are derived, it will normally be defined as an EDB relation, imported from JSON or CSV.

On the other hand, big_cities is a relation derived from the data. For these relations, we have two choides: we can (1) install them, to be used by any other definition in our model, or (2) include their definition as part of the query, making them a temporary relation used only in that scope, as we did above.

Raw Data vs. Derived Relations

Rel notebooks are reactive: the results of a Query cell are automatically updated when you make changes elsewhere in the notebook or database that affect that query.

Install Cells

When you run code in an Install cell, this code is installed into the database and persisted. Definitions in these cells are permanently available to not only other cells in the notebook, but to all notebooks in the current database.

Let’s take a simple example, which defines a relation called city_population:

install
def city_population = {
("New York, NY", 8804190);
("Los Angeles, CA", 3898747 );
}

Now, you can query or use city_population in any cell of any notebook in the current database.

Since definitions add up, a new install cell with the following code

install
def city_population = ("Cambridge, MA", 118403)

adds “Cambridge, MA” to the relation city_population(without overwriting it). That is, the new code is unioned with the original definition. We can verify the update by noting that the output of Query cell with city_population lists now three entries.

Because our notebooks are reactive, the Query cell updates automatically.

Install cells are generally useful to organize your data modeling. We can even refer to relations we have defined in other Install cells. In the following code, for example, we define big_cities as:

install
def big_cities(city) = city_population[city] > 10^6

You can see the results for big_cities by entering it into a Query cell:

If you decide to change the definition of a big city in your database, you simply modify the code block and run it again.

For instance, if you modify the code above (in the same install cell) to read:

install
def big_cities(city) = city_population[city] > 10^5

a big city is now any city with a population greater than 100,000 instead of 1,000,000.

For the most part, you will want to use Install cells to run code that defines new logic on top of existing data (“views” on data) but does not change the data themselves. Check out the Installing Models guide for more details about installing Rel programs.

For projects with small data, you can define the data in IDB relations using Install cells. For larger datasets, the best practice is to use EDB relations (see concept guide Working with EDB ) . To create, delete, or change EDB data you need to use Update cells.

Naming Sources

When you open a database in the RelationalAI Console, you see a list of notebooks on the left and a list of sources on the right. When you create an Install cell, a new source is added to the list.

You can name your source by changing the text in the box that appears to the right of the Cell Type dropdown menu. This is useful if you want to edit the code for the Install cell directly from the sources list.

Update Cells

Update cells let you change the data for certain relations in the database. Update cells change what’s known as EDB data: this might be a table of employees and their related information, or a list of inventoried products. For more information on working with EDB relations, see Updating Data: Working with EDB Relations.

For example, you might use def delete:employee = employee to clear out the EDB relation called “employee”, or def insert:employee = "Clarissa Dalloway" to insert “Clarissa Dalloway” into this employee relation. In other words, Update cells are transactional; changes made with Update cells persist in the database, even if you delete the cell’s code later.

You can think of Update cells as “action” or “execute” cells. They run only when you run them manually, by clicking the “Run” button (the triangle at the right of the input pane) or pressing SHIFT + ENTER.

To add data to a relation called employee, for example, you could run the following in an Update cell:

update
def insert:employee = {(1, "Han Solo"); (2, "Bart Simpson")}

The code runs once, and the employee relation appears as follows:

Later, in the same cell, you can run similar code to add to employee:

update
def insert:employee = {(3, "Tyrone Slothrop"); (4, "Clarissa Dalloway")}

Again, the code runs once, and employee now contains the following data:

You could also delete data by using code along the following lines:

update
def delete:employee = (3, "Tyrone Slothrop")

Now, we have

If you had run def insert:employee = {(3, "Tyrone Slothrop"); (4, "Clarissa Dalloway")} in an Install cell, this delete would not work, because the install cell re-inserts the data every time it runs. That’s one reason to make changes to data using Update cells.

Uploading Files

You can upload CSV or JSON data directly using Update cells.

To upload a CSV file:

  1. Select Update as the cell type.
  2. Click the Add Input icon at the top left of the cell.
  3. Enter a name for the relation, such as employee_data
  4. Choose a file with valid CSV format to upload (max. 100 MB), and enter code along the following lines:
update
def config[:data] = employee_data
def insert:mycsv = lined_csv[load_csv[config]]
  1. Click the “Run” button (the triangle at the right of the input pane) or press SHIFT + ENTER.

For more information on importing CSV data, see CSV Import.

To upload a JSON file:

  1. Select Update as the cell type.
  2. Click the “Add Input” icon at the top left of the cell.
  3. Enter a name for the relation, such as uploaded_json
  4. Choose a file with valid JSON to upload, and enter code along the following lines:
update
def config[:data] = uploaded_json
def insert:myjson = load_json[config]
  1. Click the “Run” button (the triangle at the right of the input pane) or press SHIFT + ENTER.

For more information on importing JSON data, see JSON Import and Export.

More generally, this file upload mechanism can be used to upload arbitrary string data, which can be further processed (as we do above with the CSV and JSON string), or saved directly as a string-valued relation.

Markdown Cells

Markdown cells let you add explanatory text in the markdown format. You can use any valid Markdown code:


## Notebook Explanation

Use _Markdown_ to add explanatory text to your notebook.

Once you are satisfied with your Markdown, you can use Toggle Folding to hide the cell. To use Toggle Folding, mouse over the area to the left of a cell and click the “eye” icon.

Exporting and Importing Notebooks

You can export and import notebooks to your local system. Notebooks are saved in JSON.

To export a notebook:

  1. Click the three dots in the upper right corner of a notebook and choose Export Notebook
  2. In the dialog box that opens, choose Save.

The notebook saves in your Downloads folder with the default name “<notebook-name>.json”.

To import a notebook:

  1. Click the three dots in the upper right corner of a notebook and choose Import Notebook
  2. Browse to the location of the notebook file and click Open.

Importing a notebook overwrites the entire existing notebook with the contents of the imported notebook.

Using Keyboard Shortcuts

Notebooks use key mappings that are similar to Emacs. Commonly-used examples appear below. For a complete list, see: https://codemirror.net/doc/manual.html#keymaps. Note: some of the key mappings in this link may not work with notebooks.

Keyboard ShortcutCommand
Ctrl-shift-enterRun a cell.
Ctrl-enterRun a cell and add a new cell.
Ctrl-D (PC), Cmd-D (Mac)Delete entire line, including newline at the end.
Ctrl-Home (PC), Cmd-Up (Mac), Cmd-Home (Mac)Move cursor to start of cell.
Ctrl-End (PC), Cmd-End (Mac), Cmd-Down (Mac)Move cursor to end of cell
Ctrl-U (PC), Cmd-U (Mac)Undo the last change to the selection.
Alt-Left (PC), Ctrl-A (Mac)Move the cursor to the start of the line.
TabIf something is selected, indent it by one indent unit. If nothing is selected, insert a tab character.
Ctrl-] (PC), Cmd-] (Mac)Indent the current line or selection by one indent unit.
Ctrl-[ (PC), Cmd-[ (Mac)Dedent the current line or selection by one indent unit.
Ctrl-A (PC), Cmd-A (Mac)Select the entire contents of the cell.
Alt-Left (PC), Ctrl-A (Mac)Move the cursor to the start of the line.
Alt-Right (PC), Ctrl-E (Mac)Move the cursor to the end of the line.
Alt-dragCreate multiple cursors.